基本上,我接受一个事件名称作为字符串,以获取EventInfo.然后,我使用反射发现事件处理程序类型和事件参数类型,创建该类型的新委托(myEventHandler),并将其与事件挂钩.当调用myEventHandler时,我需要向下转换并将参数传递给处理程序.
我的代码如下.当调用’d’时,需要通过myEventHandler调用’handler’.我需要在那里放一些反射发射代码???有什么想法吗?
EventHandler handler = delegate(object sender,EventArgs eventArgs) { //something will happen here }; Type[] typeArgs = { typeof(object),derivedEventArgsType }; DynamicMethod myEventHandler = new DynamicMethod("",typeof(void),typeArgs); var ilgen = myEventHandler.GetILGenerator(); //What should be the IL code here to //cast derviedEventArgs to EventArgs and //invoke the 'handler' above?????? ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Ret); Delegate d = dynamic.CreateDelegate(derviedEventHandlerType); //addMethod is the add MethodInfo for an Event addMethod.Invoke(target,new object[] { d });
编辑:基于通过Reflector的观察.
.method public hidebysig instance void <Main>b__1(object sender,class ConsoleApplication2.MyEventArgs e) cil managed { .maxstack 8 L_0000: nop L_0001: ldarg.0 L_0002: ldfld class [mscorlib]System.EventHandler ConsoleApplication2.Program/<>c__DisplayClass3::handler L_0007: ldarg.1 L_0008: ldarg.2 L_0009: callvirt instance void [mscorlib]System.EventHandler::Invoke(object,class [mscorlib]System.EventArgs) L_000e: nop L_000f: ret }
这就是我在此基础上尝试的.
ilgen.Emit(OpCodes.Nop); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldfld,eh.GetType().GetField("handler")); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Ldarg_2); ilgen.EmitCall(OpCodes.Callvirt,eh.handler.Method,new Type[]{ typeof(object),typeof(EventArgs) }); ilgen.Emit(OpCodes.Nop); ilgen.Emit(OpCodes.Ret);
但这会导致运行时错误:
‘Calling convention must be varargs’
可能我错过了一些东西,需要更好地了解IL.
解决方法
事实证明,我的事情过于复杂!巴里凯利
had the right idea:
static T CastDelegate<T>(Delegate src) where T : class { return (T)(object)Delegate.CreateDelegate( typeof(T),src.Target,src.Method,true); // throw on fail }
这适用于我的测试用例.