我正在尝试学习一些有关动态生成事件处理程序的知识,但在尝试重新创建这种简单情况时遇到了困难:
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上的示例,但被卡住了,然后尝试将事情展开为一个我可以开始工作的简单示例。