Почему `dynamicMethod.CreateDelegate (typeof (Action)). Method.Invoke (null, new object [0]);` создает исключение? - PullRequest
0 голосов
/ 21 сентября 2018

Кажется, это работает, предоставляя (странный) способ вызова Action:

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

Это работает, предоставляя (полезный) способ создания Action:

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

Однако, это выдает Exception:

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

MethodInfo должен быть объектом MethodInfo во время выполнения.

Вопрос: Почему из приведенного выше фрагмента кода выдается Exception?


Пример рабочего кода

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

В результате Console пишет:

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)
  [...]

Мысли

Я пробовал несколько вариантов вызова action.Method.Invoke(), но все виды изменений аргументов вызова, похоже, не меняют сообщение об исключении,

MethodInfo должен быть объектом MethodInfo времени выполнения.

Я предполагаю, что action.Method не является " MethodInfo времени выполнения ", несмотря на то, что " MethodInfo ».Я не совсем уверен, каково различие между временем выполнения - MethodInfo и не временем выполнения - MethodInfo, однако.

1 Ответ

0 голосов
/ 21 сентября 2018

MethodInfo - абстрактный тип, имеющий несколько реализаций.

Одна из них - внутренний тип System.Reflection.RuntimeMethodInfo.Вот что вы получаете, когда отражаете методы существующих типов времени выполнения:

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

С другой стороны, DynamicMethod.CreateDelegate использует другую реализацию MethodInfo:

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

Икажется, он не поддерживает вызов MethodInfo.Invoke.

Но если по какой-то причине вы не можете использовать метод Invoke созданного вами делегата (например, потому что вы не знаете точный тип делегата), вы все еще можете использовать метод Delegate.DynamicInvoke (однако динамический вызов делегата почти такой же медленный, как и 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...