【问题标题】:Why does calling a DynamicMethod with an instance of my own class cause an exception?为什么用我自己的类的实例调用 DynamicMethod 会导致异常?
【发布时间】:2010-02-08 21:45:21
【问题描述】:

我通过在运行时使用 Reflection.Emit 创建自己的函数来学习 CIL。到目前为止,我真的很惊讶事情是多么容易,但是我遇到了一些我无法猜到的东西,而且我在文档中找不到任何相关的东西。

我正在尝试创建一个简单地打印我定义的非常简单的类的函数。如果我将代码更改为打印strings,比如说,它可以工作,但是当我传递我的类A 的实例时它总是无法运行。

奇怪的是我可以注释掉我的函数体,但它仍然失败并显示TargetInvocationException。这一定很简单,但我看不到发生了什么!

class A
{
    public override string  ToString()
    {
        return "AAA!";
    }
}

class Program
{
    static void Main(string[] args)
    {
        DynamicMethod func = new DynamicMethod("func", null, new Type[] { typeof(A) });

        ILGenerator il = func.GetILGenerator();

        //il.Emit(OpCodes.Ldarg_0);
        //il.Emit(OpCodes.Box, typeof(A));
        //il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(A) }));

        il.Emit(OpCodes.Ret);

        func.Invoke(null, new object[] { new A() });

        Console.Read();
    }
}

我做错了什么来引发异常?为什么这只发生在我的课程中?

【问题讨论】:

    标签: c# .net reflection cil dynamicmethod


    【解决方案1】:

    其实挺傻的。我在这上面花了几个小时,但是当我听从 Laurent Etiemble 的建议并创建了一个委托时,我得到的异常告诉我我的 A 类不公开。

    解决方案:在class A前添加public关键字。完美运行。我知道这一定是非常简单的事情。

    【讨论】:

      【解决方案2】:

      问题很简单,但并不明显。首先,不要像已经指出的那样将论点装箱。但真正的问题是 A 类不是公开的。您正在使用的 Invoke 函数的默认绑定(而不是完整绑定)是仅查找公开方法。因为 A 是一个非公共类,这意味着它无法找到您的函数(我知道这很神奇)并且失败了。

      【讨论】:

      • 我意识到几乎就像你发布的那样。因此,我的回答也是如此。这是正确的答案!
      • 有时会喜欢反思,几乎从不给你明智的答案,尤其是当你尝试对象或字符串时,它只是因为它们是公开的,grr :)
      【解决方案3】:

      首先 - 你不应该发出 Box 操作码,因为 A 是一个类,不需要装箱。装箱仅适用于值类型。

      第二 - 它失败的原因是因为该方法没有访问 A 类的权限(它不是公共的)。要么使 A public 要么您可以通过使用 this constructor 并将 true 传递给 skipVisibility 参数来指示 JIT 编译器跳过可见性检查。

      【讨论】:

      • 但即使有注释的行也会引发异常。
      • 我编辑了我的回复以包含失败的真正原因。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-19
      • 2011-10-01
      • 2010-09-16
      • 2020-12-11
      • 1970-01-01
      相关资源
      最近更新 更多