为什么在动态创建事件处理程序时会出现Argumentexception?

美好的一天

我写了以下方法:

private void RegisterEvent(object targetObject, string eventName, string methodName) { EventInfo eventInfo = targetObject.GetType().GetEvent(eventName); MethodInfo method = eventInfo.EventHandlerType.GetMethod("Invoke"); IEnumerable types = method.GetParameters().Select(param => param.ParameterType); DynamicMethod dynamicMethod = new DynamicMethod(eventInfo.EventHandlerType.Name, typeof (void), types.ToArray(), typeof (QueryWindow)); MethodInfo methodInfo = typeof (QueryWindow).GetMethod(methodName, new[] { typeof (object) }); ILGenerator ilGenerator = dynamicMethod.GetILGenerator(256); ilGenerator.Emit(OpCodes.Ldarg_1); ilGenerator.EmitCall(OpCodes.Call, methodInfo, null); dynamicMethod.DefineParameter(1, ParameterAttributes.In, "sender"); dynamicMethod.DefineParameter(2, ParameterAttributes.In, "e"); // Get an argument exception here Delegate methodDelegate = dynamicMethod.CreateDelegate(eventInfo.EventHandlerType, this); eventInfo.AddEventHandler(targetObject, methodDelegate); } 

我收到带有消息的ArgumentException

绑定到目标方法时出错。

在线

 Delegate methodDelegate = dynamicMethod.CreateDelegate(eventInfo.EventHandlerType, this); 

谁能指出我的错误?

提前致谢。

假设methodNameQueryWindow的静态方法,这应该工作:

 private static void RegisterEvent(object targetObject, string eventName, string methodName) { var eventInfo = targetObject.GetType().GetEvent(eventName); var method = eventInfo.EventHandlerType.GetMethod("Invoke"); var types = method.GetParameters().Select(param => param.ParameterType); var methodInfo = typeof(QueryWindow).GetMethod(methodName, new[] { typeof(object) }); // replaced typeof(void) by null var dynamicMethod = new DynamicMethod(eventInfo.EventHandlerType.Name, null, types.ToArray(), typeof(QueryWindow)); ILGenerator ilGenerator = dynamicMethod.GetILGenerator(256); // Using Ldarg_0 to pass the sender to methodName ; Ldarg_1 to pass the event args ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.EmitCall(OpCodes.Call, methodInfo, null); // Added return ilGenerator.Emit(OpCodes.Ret); // Removed parameter definition (implicit from DynamicMethod constructor) // Removed the target argument var methodDelegate = dynamicMethod.CreateDelegate(eventInfo.EventHandlerType); eventInfo.AddEventHandler(targetObject, methodDelegate); } 

编辑:

由于您可以使用.NET 3.5,因此您应该创建表达式树。 这是另一个解决方案:

 public class QueryWindow { public void RegisterEvent(object targetObject, string eventName, string methodName) { var eventInfo = targetObject.GetType().GetEvent(eventName); var sender = Expression.Parameter(typeof (object), "sender"); var e = Expression.Parameter(typeof (EventArgs), "e"); var body = Expression.Call(Expression.Constant(this), methodName, null, e); var lambda = Expression.Lambda(eventInfo.EventHandlerType, body, sender, e); eventInfo.AddEventHandler(targetObject, lambda.Compile() ); } public void OnEvent(object o) { Console.WriteLine(o); } } 

请注意, OnEvent方法不再是静态的。 我还假设您尝试订阅的事件是遵循.NET约定的事件(sender + event args)。 这样,我们可以利用逆变并始终传递一个类型的lambda:

 (object sender, EventArgs e) => { /* */ } 

dynamicMethod.CreateDelegate(eventInfo.EventHandlerType,this);

这个论点不正确。 它引用了您的类,即生成动态类型的类。 当然你需要targetObject

调用DynamicMethod.CreateDelegate ,不应传递目标参数。

编辑:

我想你还必须使第一个参数= 0,并相应地更改codegen。