45

I want to get an action delegate from a MethodInfo object. Is this possible?

IAbstract
  • 19,551
  • 15
  • 98
  • 146
mokaymakci
  • 1,373
  • 1
  • 18
  • 30

2 Answers2

79

Use Delegate.CreateDelegate:

// Static method
Action action = (Action) Delegate.CreateDelegate(typeof(Action), method);

// Instance method (on "target")
Action action = (Action) Delegate.CreateDelegate(typeof(Action), target, method);

For an Action<T> etc, just specify the appropriate delegate type everywhere.

In .NET Core, Delegate.CreateDelegate doesn't exist, but MethodInfo.CreateDelegate does:

// Static method
Action action = (Action) method.CreateDelegate(typeof(Action));

// Instance method (on "target")
Action action = (Action) method.CreateDelegate(typeof(Action), target);
IAbstract
  • 19,551
  • 15
  • 98
  • 146
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Upvoted. How to apply this to DataEventArgs ? http://stackoverflow.com/questions/33376326/how-to-create-generic-event-delegate-from-methodinfo – Jeson Martajaya Oct 27 '15 at 18:57
  • `Delegate.CreateDelegate` does not appear to be available in .Net Core. Any ideas there? – IAbstract May 05 '17 at 13:41
  • 1
    @IAbstract: Interesting - I hadn't spotted that. You can call `MethodInfo.CreateDelegate` instead. (Just tried it, and it worked fine.) – Jon Skeet May 05 '17 at 13:48
  • @JonSkeet: yeah, actually found that and appreciate adding to answer. +1 for completeness!!! – IAbstract May 05 '17 at 16:01
  • @JonSkeet [side-bar & food for thought] re: Delegate vs MethodInfo in `try-catch` blocks. I discovered the much perturbing failure of try-catch blocks when invoking a MethodInfo (e.g., obtained via reflection). However, if a delegate is created from the MethodInfo and cast to a `Delegate` sub-class - i.e., Action, Func - and executed in a try-catch block, any exceptions are caught as expected. – IAbstract May 05 '17 at 19:22
  • 1
    @IAbstract: That sounds very odd. Possibly ask about it in a new question? – Jon Skeet May 05 '17 at 20:01
  • Can a parameter be passed into this delegate? – Douglas Gaskell Dec 18 '18 at 23:38
  • @DouglasGaskell: Not an `Action`, no. If you want a delegate with an argument, pick a delegate with a signature matching what you want. – Jon Skeet Dec 19 '18 at 06:50
1

This seems to work on top of John's advice too:

public static class GenericDelegateFactory
{
    public static object CreateDelegateByParameter(Type parameterType, object target, MethodInfo method) {

        var createDelegate = typeof(GenericDelegateFactory).GetMethod("CreateDelegate")
            .MakeGenericMethod(parameterType);

        var del = createDelegate.Invoke(null, new object[] { target, method });

        return del;
    }

    public static Action<TEvent> CreateDelegate<TEvent>(object target, MethodInfo method)
    {
        var del = (Action<TEvent>)Delegate.CreateDelegate(typeof(Action<TEvent>), target, method);

        return del;
    }
}
JoshGough
  • 964
  • 1
  • 8
  • 16