为什么在动态创建事件处理程序时会出现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);
谁能指出我的错误?
提前致谢。
假设methodName
是QueryWindow
的静态方法,这应该工作:
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。