我正在尝试学习动态生成事件处理程序的相关知识,但是在尝试重新创建这个简单的情况时遇到了困难:
public delegate void SomethingHappenedEventHandler(object sender, object args);
public event SomethingHappenedEventHandler SomethingHappened;
// This is the event handler that I want to create dynamically
public void DoSomething(object a, object b)
{
DoSomethingElse(a, b);
}
public void DoSomethingElse(object a, object b)
{
Console.WriteLine("Yay! " + a + " " + b);
}
我使用反编译器生成了DoSomething方法的IL代码,它给出了:
.method public hidebysig instance void DoSomething(object a, object b) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldarg.1
L_0002: ldarg.2
L_0003: call instance void MyNamespace::DoSomethingElse(object, object)
L_0008: ret
}
所以,我编写了以下代码来动态生成并执行与DoSomething(...)等效的方法:
public void CreateDynamicHandler()
{
var eventInfo = GetType().GetEvent("SomethingHappened");
var eventHandlerType = eventInfo.EventHandlerType;
var dynamicMethod = new DynamicMethod("DynamicMethod", null, new[] { typeof(object), typeof(object) }, GetType());
var ilgen = dynamicMethod.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldarg_1);
ilgen.Emit(OpCodes.Ldarg_2);
MethodInfo doSomethingElse = GetType().GetMethod("DoSomethingElse", new[] { typeof(object), typeof(object) });
ilgen.Emit(OpCodes.Call, doSomethingElse);
ilgen.Emit(OpCodes.Ret);
Delegate emitted = dynamicMethod.CreateDelegate(eventHandlerType);
emitted.DynamicInvoke("hello", "world");
}
然而,当我运行这个程序时,我会收到一个InvalidProgramException: JIT编译器遇到了内部限制的错误。
有人能指出我哪里错了吗?
[编辑] 正如几位评论者所指出的那样,如果我知道所有涉及的类型,整个IL生成过程是不必要的。我这样做的原因是,这是在运行时动态生成事件处理程序的第一步,对于我不知道所有涉及类型的事件。基本上,我一直在按照http://msdn.microsoft.com/en-us/library/ms228976.aspx的示例进行操作,卡住了,然后试图将事情解开成一个简单的示例,以便我可以使其工作。
MethodBase.Invoke()
调用它们,或者您可以使用dynamic
类型。 - Timwiobject[]
的参数的单个处理程序。 - Timwi