Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `dynamicMethod.CreateDelegate(typeof(Action)).Method.Invoke(null,new object[0]);` throw an Exception?

This seems to work, providing a (weird) way to call an Action:

Action action = () => { };
action.Method.Invoke(action.Target, new object[0]);

This seems to work, providing a (helpful) way to create an Action:

var action = dynamicMethod.CreateDelegate(typeof(Action)) as Action;
action();

However, this throws an Exception:

var action = dynamicMethod.CreateDelegate(typeof(Action)) as Action;
action.Method.Invoke(action.Target, new object[0]);  // Throws exception

MethodInfo must be a runtime MethodInfo object.

Question: Why is the above code snippet throwing an Exception?


Working code example

var dynamicMethod = new System.Reflection.Emit.DynamicMethod(
            ""
        ,   typeof(void)
        ,   new Type[0]
    );

var ilGenerator = dynamicMethod.GetILGenerator();
ilGenerator.Emit(System.Reflection.Emit.OpCodes.Ret);
var action = dynamicMethod.CreateDelegate(typeof(Action)) as Action;

try
{
    action.Method.Invoke(action.Target, new object[0]);
}
catch (Exception exception)
{
    System.Console.WriteLine(exception);
}

This causes the Console to write:

Exception thrown: 'System.ArgumentException' in mscorlib.dll
System.ArgumentException: MethodInfo must be a runtime MethodInfo object.
Parameter name: this
  at System.Reflection.Emit.DynamicMethod.RTDynamicMethod.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
  at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
  [...]

Thoughts

I've tried a bunch of variations on calling action.Method.Invoke(), but all sorts of variations on the call arguments don't seem to change the exception-message,

MethodInfo must be a runtime MethodInfo object.

My guess is that action.Method isn't a "runtime MethodInfo", despite being a "MethodInfo". I'm not really sure what the distinction between a runtime-MethodInfo and a non-runtime-MethodInfo might be, though.

like image 292
Nat Avatar asked Sep 09 '26 01:09

Nat


1 Answers

MethodInfo is an abstract type, which has several implementations.

One of them is the internal type System.Reflection.RuntimeMethodInfo. This is what you get when you reflect the methods of existing runtime types:

Console.WriteLine(typeof(object).GetMethod("ToString").GetType().FullName); // System.Reflection.RuntimeMethodInfo

On the other hand, DynamicMethod.CreateDelegate uses another implementation of MethodInfo:

Console.WriteLine(action.Method.GetType().FullName); // System.Reflection.Emit.DynamicMethod+RTDynamicMethod

And it seems it does not support invocation by MethodInfo.Invoke.

But if you cannot use the Invoke method of your created delegate for some reason (because you don't know the exact delegate type, for example), you still can use the Delegate.DynamicInvoke method (however, dynamic invocation of a delegate is almost as slow as the reflection API):

Delegate del = action; // let's assume you don't know the delegate type
del.DynamicInvoke(); // slow as hell but works without throwing an exception
like image 187
György Kőszeg Avatar answered Sep 11 '26 15:09

György Kőszeg



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!