4

I have a System.Reflection.MethodInfo and would like to have a method that creates a delegate(preferably a Func<...> or an Action<...>) that represents that method, given an instance to invoke it on.

So ideally I would like something like the following psuedo-code:

public TDelegate GetMethod<TDelegate>(MethodInfo methodToRepresent, object instanceToInvokeOn)
{
    return (TDelegate)((parameters....) => methodToRepresent.Invoke(instanceToInvokeOn, all parameters in an object[]));
}

where TDelegate represents the signature of the represented method. If the signatures don't match, an exception should be thrown.

I realise I probably can't achieve this with a simple lambda expression, since its parametertypes must be known at compile-time. Perhaps I need to construct a delegate from scratch? Is it possible to create a delegate by specifying its body and parameters seperately?

Thank you

JBSnorro
  • 6,048
  • 3
  • 41
  • 62

2 Answers2

3

I don't really understand your question. But perhaps you want this:

public TDelegate GetMethod<TDelegate>(MethodInfo methodToRepresent, object instanceToInvokeOn)
  where TDelegate:class
{
   return (TDelegate)(object)Delegate.CreateDelegate(typeof(TDelegate), instanceToInvokeOn, methodToRepresent);
}
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
2

You can do this with the following method. Note that you can't really create a generic Action<...> using this method because, as you say, the types are not known at compile time. But this gets you pretty close.

public delegate void DynamicInvokeDelegate(params object[] args);

public static DynamicInvokeDelegate CreateDynamicInvokeDelegate(MethodInfo method, object instance) {
    return args => method.Invoke(instance, args);
}

If you need the delegate to return a value:

public delegate object DynamicInvokeWithReturnDelegate(params object[] args);

public static DynamicInvokeWithReturnDelegate CreateDynamicInvokeWithReturnDelegate(MethodInfo method, object instance) {
    return args => method.Invoke(instance, args);
}

EDIT:

It actually looks like you might be wanting this code:

public static T GetDelegate<T>(MethodInfo method, object instance)
    where T : class
{
    return (T)(object)Delegate.CreateDelegate(typeof(T), instance, method);
}

The (object) cast is required, since the compiler will not allow you to cast Delegate to any random type, and you cannot constrain T to be a delegate. Casting through object satisfies the compiler.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • Yup, thats about identical. I wouldn't have settled for the solution with the params object[], though. Thnx anyway – JBSnorro Nov 14 '10 at 18:49
  • OT: but I just wanted to say welcome and congrats after a really successful and active first week on stackoverflow. Thanks for contributing ;p – Marc Gravell Nov 15 '10 at 17:20