为什么使用我自己的类的实例调用 DynamicMethod 会导致异常?

发布于 2024-08-20 12:34:50 字数 967 浏览 11 评论 0原文

我正在通过使用 Reflection.Emit 在运行时创建自己的函数来学习 CIL。实际上,我很惊讶到目前为止事情是如此简单,但我遇到了一些我无法猜测的事情,而且我在文档中找不到任何相关内容。

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

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

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

我做错了什么导致这个异常?为什么这种情况只发生在我的课程中?

I'm learning CIL by making my own functions at runtime with Reflection.Emit. I'm actually surprised how easy things have been up until now but I've hit something that I can't guess my way through and I can't find anything relative in the docs.

I'm trying to create a function that simply prints a very simple class I have defined. If I change my code to print strings, say, it works but it always fails to run when I pass an instance of my class A.

What's weird is I can comment out my function body and it still fails with a TargetInvocationException. It must be quite simple but I can't see what's up!

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

What am I doing so wrong to make this raise an exception? Why does this only happen with my classes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你对谁都笑 2024-08-27 12:34:50

实际上这很愚蠢。我花了几个小时在这上面,但是当我遵循 Laurent Etiemble 的建议并创建一个委托时,我得到的异常告诉我我的 A 类不是公开的。

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

It was quite silly actually. I spent several hours on this but when I followed Laurent Etiemble's advice and created a delegate the exception I got told me my class A wasn't public.

Solution: Add the public keyword before class A. Works perfectly. I knew it had to be something insanely simple.

韶华倾负 2024-08-27 12:34:50

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

The problem is simple but not-obvious. For a start don't box the argument as already pointed out. But the real problem is the A class is not public. The default binding for the Invoke function you are using (rather than the full one) is to only find publicly methods. Because A is a non-public class it means it fails to find your function (amazing I know) and fails.

难得心□动 2024-08-27 12:34:50

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

其次 - 它失败的原因是因为该方法没有访问类 A 的权限(它不是公共的)。要么使 A public 或者您可以使用 此构造函数 并将 true 传递给skipVisibility 参数。

First - You shouldn't be emitting the Box opcode since A is a class and doesn't need to be boxed. Boxing is only for value types.

Second - The reason why it's failing is because the method doesn't have permission to access class A (it's not public). Either make A public OR You can instruct the JIT compiler to skip visibility checks by using this constructor and passing true to the skipVisibility parameter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文