如何在C#中传递一个函数作为参数?

是否有可能在C#中传递一个函数作为参数? 我可以使用Func或Action类来完成,但这迫使我一次声明整个函数签名。 当我尝试使用委托,我得到一个编译错误,说它不能将方法组转换为委托。

我正在使用Axial ,我试图让用户调用Web服务。 我要去的是能够创buildVisual Studio代理类,然后传入生成的函数。 函数签名并不重要,因为生成的代码只使用函数名称。 然而,我想传递的function,而不是名称有两个原因:能够使用代理的URL属性和编译器错误,如果Web服务不存在或在Visual Studio中更新。

public void AlertIt(object o) { Axial.DOM.Window.Alert(o.ToString()); } public void CallAddService() { object[] param = new object[] { int.Parse(txtA.Text), int.Parse(txtB.Text) }; Axial.ServerScript.CallWebService(new WSProxy.WS().Add, param, AlertIt, AlertIt); } class Axial.ServerScript { public void CallWebService(Delegate method, object[] param, Action<object> successCallback, Action<object> failureCallback) { // translate to javascript (already working) } } 

我想你想要的是:

 static object InvokeMethod(Delegate method, params object[] args){ return method.DynamicInvoke(args); } static int Add(int a, int b){ return a + b; } static void Test(){ Console.WriteLine(InvokeMethod(new Func<int, int, int>(Add), 5, 4)); } 

打印“9”。

将方法组,匿名方法或lambdaexpression式转换为委托需要编译器知道确切的委托types。 但是,您可以使用lambdaexpression式和捕获的variables来简化:

 public void InvokeMethod(Action action) { action(); } public int Add(int a, int b) { return a + b; } public void Test() { InvokeMethod(() => Add(2, 3)); } 

这基本上延迟调用正常的方式,但通过包装实际的调用Add一个普通的Action委托。

如果这不符合您的要求,也许您可​​以告诉我们更多关于您真正想要达到的目标。

编辑:如果这是生成的代码,你可以Func<...>types参数转换为Func<...> – 假设没有太多。 除此之外,没有办法通过方法组。 偶尔会有一个“infoof(…)”操作符的调用(像typeof,但是对于成员),这会给你一个MemberInfo,但实际上并不存在。

你应该先有一个委托

 delegate int Operation(int a, int b) 

那么它变成:

 public void InvokeMethod(Operation method, object target, object param) { method((int) target, (int) param); } 

无需调用任何调用。

和dbone一样,我不确定为什么你需要一个params []数组。 你会澄清扩大的参数用法吗?

此外,我将不得不纠正你的问题,因为它会导致编译错误:p

请看看使用代表这里是一个很好的例子

委托示例

你为什么要用reflection? 会不会有不同数量的参数? 或者你知道方法signture将保持不变(还记得C#支持params []关键字)

参数c#

HTH

骨头

请看Justin Etheredge的函数式编程系列 。 你应该find解决你的问题。

这是一个非常简单的例子,对于已经熟悉( C / C ++ / VB.NET/Python )风格的通过指针/ ref (使用C#委托 )传递函数的程序员来说:

  delegate void CALLBACK(String s); static void Main(string[] args) { Get("some string", testfunc); Util.pause(); } static void Get(String s, CALLBACK x) { x(s); } static void testfunc(String s) { Console.WriteLine(s); } 

说如果您需要传递方法作为参数以及您需要捕获返回值进一步处理。 然后上面的例子将正常工作。 但是,如果你需要传递一个void返回types的方法,那么你需要创build一个更多的InvokeMethod函数版本。 检查下面的例子。

 private static T retry<T>(Delegate method, params object[] args) { for (int i = 0; i <= 3; i++) { try { return (T)method.DynamicInvoke(args); } catch (Exception ex) { if (i == 3) { logMessage(ex.Message); } Console.WriteLine("Retry count " + i); Thread.Sleep(10); } } return default(T); } private static void retry2(Delegate method, params object[] args) { for (int i = 0; i <= 3; i++) { try { method.DynamicInvoke(args); break; } catch (Exception ex) { if (i == 3) { logMessage(ex.Message); //return default(T); } Console.WriteLine("Retry count " + i); Thread.Sleep(10); } } } static bool isSuccess = true; static void logMessage(string msg) { isSuccess = false; Console.WriteLine(msg); } static int Add(int a, int b) { return a + b; } static void Add2(int a, int b) { int c = a + b; Console.WriteLine(c); } static void Main(string[] args) { int d = retry<int>(new Func<int, int, int>(Add), 6, 7.7); Console.Write(" " + d + "\n"+isSuccess); retry2(new Action<int, int>(Add2), 45, 60); Console.ReadKey(); } 

像这样的东西应该为你工作:

 delegate int MyDelegate(int a, int b); public int Add(int a, int b) { return a + b; } public void InvokeMethod(Delegate method, object[] param) { Console.WriteLine(method.DynamicInvoke(param)); } public Form1() { InitializeComponent(); InvokeMethod(new MyDelegate(Add), new object[] { 1, 2 }); } 

祝你好运!