3

Is there a way to send a any method as a parameter? I need to do it for all kind of method, not caring about signatures and returns. Say something like this (bad code, just for the idea):

public class Foo
{
...
void TestMethod(DontKnowWhatToPutHere theDelegate) {}
...
}

...

foo.TestMethod(-foo.AnotherMethod(1,2)-);
foo.TestMethod(-foo.AnotherMethod("I don't care method signature nor returning type")-);

I tried with no success to do it with Action as parameter.

What I need to do is to send any method to a function, and then use reflection to get method name and parameters, so if there's another way you guys can figure out, I would gladly hear about it too.

casperOne
  • 73,706
  • 19
  • 184
  • 253
Chuck Norris
  • 963
  • 1
  • 9
  • 17
  • Use a `string`. If you're going to inspect the class anyway, you don't have *that* much to gain by knowing that some methods by the desired name exist. – millimoose Oct 01 '12 at 16:52
  • Hey Please have a look at here http://stackoverflow.com/questions/380198/how-to-pass-a-function-as-a-parameter-in-c it is an exact replica of what you are asking I guess – Aravind.HU Oct 01 '12 at 16:52

3 Answers3

9

No. The compiler always has to be able to identify a specific delegate to convert to, and there's no single delegate type which is compatible with all method signatures. You can get a long way by using Action, Action<T>, Action<T1, T2> etc, then Func<TResult>, Func<T1, TResult> etc... but even that's going to fail when it comes to out and ref parameters. Additionally, there's overload resolution to consider.

Additionally, your syntax is passing the result of a method invocation, which isn't the same thing as passing a method in the first place. (That's ignoring the - prefix/suffix, which appears to be made-up syntax.)

What you could use is Expression<Action> and wrap the method call:

void TestMethod(Expression<Action> action)
{
    ...
}

Then:

foo.TestMethod(() => foo.AnotherMethod(1,2));

Within TestMethod you can then look into the expression tree to find out that it's a method call, work out the target, the parameters etc. See the MSDN page on expression trees for more information.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • +1. Especially for `Expression` - pattern used in many unit test frameworks. – Alexei Levenkov Oct 01 '12 at 17:00
  • Great! This is good. Now I got `((MethodCallExpression)action.Body).Method.Name` and `((MethodCallExpression)action.Body).Method.GetParameters()` that gives me what I need, except by the `AnotherMethod` parameters values. I've researched and found that I can't get parameters values using reflection, is there any workaround in order to get this/these parameters? (other than sending `object[] parameters` as a `TestMethod` parameter) – Chuck Norris Oct 01 '12 at 17:43
  • @ChuckNorris: You can get the arguments from the `MethodCallExpression.Arguments` property. (I assume you want to know the arguments you're calling it with, not just the parameter types declared by the method.) – Jon Skeet Oct 01 '12 at 17:51
4

You can pass MethodInfo object

void TestMethod(MethodInfo methodInfo, object methodObject, object[] parameters)
{
    methodInfo.Invoke(methodObject, parameters);
}
Dmitrii Dovgopolyi
  • 6,231
  • 2
  • 27
  • 44
0
public class Foo
{
   void TestMethod(Action<int, int> theDelegate) {}
   void TestMethod(Action<string> theDelegate) {}
}

foo.TestMethod(() => foo.AnotherMethod(1,2));
foo.TestMethod(() => foo.AnotherMethod("I don't care method signature nor returning type"));
Furqan Safdar
  • 16,260
  • 13
  • 59
  • 93
  • Any method, I don't care about method signature and returning type. This solution would make me write a TestMethod override for every each possible method. – Chuck Norris Oct 01 '12 at 17:47
  • Yea overloading is required here, but you can have a GenericTestMethod doing common task in it and is called by each overloaded method. This way you don't have replicate your TestMethod logic. – Furqan Safdar Oct 01 '12 at 17:53