是否有可能在C#中交换方法的实现,比如Objective-C中的方法混合?
所以我可以在运行时用我自己的(或在其上添加另一个)来替换现有的实现(来自外部源,例如通过dll)。
我已经搜索过这个,但没有找到任何有价值的东西。
答案 0 :(得分:5)
您可以使用delegates
让您的代码指向您希望在运行时执行的任何方法。
public delegate void SampleDelegate(string input);
以上是一个函数指针,指向任何产生void
并以string
作为输入的方法。您可以为其分配具有该签名的任何方法。这也可以在运行时完成。
也可以在MSDN上找到一个简单的教程。
编辑,根据您的评论:
public delegate void SampleDelegate(string input);
...
//Method 1
public void InputStringToDB(string input)
{
//Input the string to DB
}
...
//Method 2
public void UploadStringToWeb(string input)
{
//Upload the string to the web.
}
...
//Delegate caller
public void DoSomething(string param1, string param2, SampleDelegate uploadFunction)
{
...
uploadFunction("some string");
}
...
//Method selection: (assumes that this is in the same class as Method1 and Method2.
if(inputToDb)
DoSomething("param1", "param2", this.InputStringToDB);
else
DoSomething("param1", "param2", this.UploadStringToWeb);
您也可以使用Lambda表达式:DoSomething("param1", "param2", (str) => {// what ever you need to do here });
另一种选择是使用Strategy Design Pattern
。在这种情况下,您声明接口并使用它们来表示所提供的行为。
public interface IPrintable
{
public void Print();
}
public class PrintToConsole : IPrintable
{
public void Print()
{
//Print to console
}
}
public class PrintToPrinter : IPrintable
{
public void Print()
{
//Print to printer
}
}
public void DoSomething(IPrintable printer)
{
...
printer.Print();
}
...
if(printToConsole)
DoSomething(new PrintToConsole());
else
DoSomething(new PrintToPrinter());
第二种方法比第一种方法稍微严格,但我认为这也是另一种方法来实现你想要的。
答案 1 :(得分:1)
取代方法的唯一方法"是使用代表。
如果您的代码如下所示:
public void Foo()
{
Bar();
}
public void Bar()
{
}
然后你无法让Foo
调用除Bar
之外的任何其他方法。您在Objective-C中引用的方法分派表在.NET中是不可变的。
为了能够指定上面应该调用的Foo
方法,您需要使用delegate
:
public void Foo(Action whichMethod)
{
whichMethod();
}
你可以这样称呼它:
Foo(Bar);
Foo(Baz);
但必须构建该方法以允许这种运行时替换。
答案 2 :(得分:1)
虽然这不是强类型语言中面向对象编程的最佳途径,但值得一提的是,自.NET 4.0起,C#包含了允许动态编程的动态语言运行时(DLR)。最奇怪的动态对象之一是class_name: AcceptanceTester
modules:
enabled:
- WebDriver:
url: 'somewebsite.com'
browser: phantomjs
request_timeout: 10
:一个完全运行时可扩展的对象:
ExpandoObject
顺便说一下,正如我上面所说的,我在这里只是为了学习目的而分享了这种方法。它可能在某些边缘情况下很有用,但由于C#是一种编译且强类型的语言,因此在99.99%的情况下应该避免使用这种方法。
答案 3 :(得分:0)
void Test(Action method) {
if ( method != null ) method.invoke();
}
你可以打电话给这个
Test( () => { Console.WriteLine("hello world"); } )
更改def并再次致电
Test( () => { MessageBox.Show("Hi"); } )