代码之家  ›  专栏  ›  技术社区  ›  Nat

为什么`dynamicMethod.CreateDelegate(typeof(Action)).Method.Invoke(null,new object[0]);`抛出异常?

  •  1
  • Nat  · 技术社区  · 6 年前

    Action :

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

    这似乎是可行的,提供了一种(有用的)方法来创建 行动 :

    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对象。

    为什么上面的代码片段会抛出 例外情况 ?


    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 和非运行时- 不过,可能是。

    1 回复  |  直到 4 年前
        1
  •  2
  •   György Kőszeg    6 年前

    MethodInfo 是一个抽象类型,它有多个实现。

    其中之一是内部类型 System.Reflection.RuntimeMethodInfo . 这是反映现有运行时类型的方法时得到的结果:

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

    DynamicMethod.CreateDelegate 使用的另一个实现 :

    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