How to pass a function as a parameter in C #?

Is it possible to pass a function as a parameter in C #? I can do this using the Func or Action classes, but this forces me to declare the entire function signature immediately. When I try to use Delegate, I get a compilation error saying that it cannot convert a group of methods to a delegate.

I am working on Axial and I am trying to allow users to call web services. Why do I want to create a Visual Studio proxy class, and then pass the generated function. The signature of the function does not matter, since the generated code uses only the name of the function. However, I would like to pass a function instead of a name for two reasons: the ability to use the Url proxy resource and a compiler error if the web service does not exist or is updated in 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) } } 
+55
reflection c #
Dec 19 '08 at 5:53
source share
8 answers

I think you want:

 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)); } 

Prints "9".

+52
Dec 19 '08 at 6:27
source share

Converting a group of methods, an anonymous method, or lambda expression to a delegate requires the compiler to know the exact type of delegate. However, you could use lambda expressions and captured variables to make this easier:

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

This basically delays the call in the usual way, but by wrapping the actual Add call in a simple Action delegate.

If this does not meet your requirements, perhaps you can tell us a little more about what you are really trying to achieve.

EDIT: If this is generated code, you can apply arguments of the correct type to Func<...> - if there aren’t so many. Other than this, there is no real way to just go through a group of methods. From time to time there were calls to the operator "infoof (...)" (for example, typeof, but for participants), which would provide you with MemberInfo, but this does not actually exist.

+46
Dec 19 '08 at 8:17
source share

You must have a delegate first

 delegate int Operation(int a, int b) 

then it becomes:

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

No need to call a call.

Like dbone, I'm not sure why the params [] array is needed. Could you clarify the extended use of parameters?

Also, I will have to fix something in your question because it will cause a compilation error: p

+4
Dec 19 '08 at 6:22
source share

please take a look at using delegates, here is a great example

Delegation Example

why do you use reflection? will there ever be a different number of parameters? or you know that the signture method will remain constant (also remember that C # supports the params [] keyword)

params c #

NTN

Bones

+3
Dec 19 '08 at 6:14
source share

Check out the Justin Etheredge Feature Series. You must find a solution to your problem.

+3
Dec 19 '08 at 14:38
source share

This is a very simple example for a programmer who is already familiar with the C / C ++ / VB.NET/Python ) -style pass function using the / ref pointer (with a C # delegate ):

  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); } 
+3
Jul 26 '13 at 9:19
source share

Tell me If you need to pass a method as a parameter, and also you need to catch the return value for further processing. Then the above examples will work fine. But tell me, if you need to pass a method with a return type of void, then you need to create another version of the InvokeMethod function. See an example below.

 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(); } 
+2
Jun 23 '11 at 18:53
source share

Something like this should work for you:

 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 }); } 

Good luck

+1
Dec 19 '08 at 6:23
source share



All Articles