为什么使用我自己的类的实例调用 DynamicMethod 会导致异常?
我正在通过使用 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 string
s, 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
实际上这很愚蠢。我花了几个小时在这上面,但是当我遵循 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.问题很简单但并不明显。首先,不要像已经指出的那样对论点进行限制。但真正的问题是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.
首先 - 您不应该发出
Box
操作码,因为A
是一个类,不需要装箱。装箱仅适用于值类型。其次 - 它失败的原因是因为该方法没有访问类 A 的权限(它不是公共的)。要么使
A
public
或者您可以使用 此构造函数 并将true
传递给skipVisibility 参数。First - You shouldn't be emitting the
Box
opcode sinceA
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 passingtrue
to the skipVisibility parameter.