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

标签 c# delegates invoke system.reflection reflection.emit

这似乎有效,提供了一种(奇怪的)方法来调用 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 must be a runtime MethodInfo object.

问题为什么上面的代码片段会抛出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 must be a runtime MethodInfo object.

我的猜测是 action.Method 不是“runtime MethodInfo”,尽管它是“MethodInfo”。不过,我不太确定运行时-MethodInfo 和非运行时-MethodInfo 之间的区别是什么。

最佳答案

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

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

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调用。

但是如果由于某种原因你不能使用你创建的委托(delegate)的 Invoke 方法(例如因为你不知道确切的委托(delegate)类型),你仍然可以使用 Delegate .DynamicInvoke 方法(然而,委托(delegate)的动态调用几乎和反射 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

关于c# - 为什么 `dynamicMethod.CreateDelegate(typeof(Action)).Method.Invoke(null,new object[0]);` 抛出异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52435563/

相关文章:

c# - linq 中的 System.Guid.NewGuid() 选择

c# - 工厂模式构建许多派生类

ios - 单点触控/iOS : which place is the best one to unsubscribe the delegate

Python 调用 - 找不到任何名为 'tasks' 的集合!

javascript - 无法从 html 按钮调用 js 函数

c# - 尝试使用 AttributeRouting 创建默认的 ASP.NET MVC 路由

c# - 如何获取 LightSwitch 中 IContentItemProxy 上的 SetBinding 方法的路径?

c# - 为什么 string Method(Object object) 可能与 Func<Object, string> 委托(delegate)类型不匹配?

c++ - 使用委托(delegate)调用 C++ 函数时 VS2015 应用程序崩溃

c# - 在调用新操作时帮助理解 C# 语法