为什么我动态创建的事件处理程序时,我得到一个参数异常? [英] Why am I getting an Argument exception when creating event handler dynamically?

查看:144
本文介绍了为什么我动态创建的事件处理程序时,我得到一个参数异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好日子所有

我写了下面的方法:

private void RegisterEvent(object targetObject, string eventName, string methodName)
{
    EventInfo eventInfo = targetObject.GetType().GetEvent(eventName);
    MethodInfo method = eventInfo.EventHandlerType.GetMethod("Invoke");
    IEnumerable<Type> 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的消息

I get ArgumentException with the message

错误绑定到目标方法。

在该行

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



任何人都可以指出我的错误呢?

Could anyone point out on my mistake?

先谢谢了。

推荐答案

假设方法名是一个静态 QueryWindow 的方法,这应该工作:

Assuming that methodName is a static method of QueryWindow, this should work:

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);
}



编辑:

Edit :

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

Since you can use .NET 3.5, you should create an expression tree. Here is another solution:

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约定(发件人+事件参数)的事件。通过这种方式,我们可以利用逆变始终传递型的lambda:

Notice that the OnEvent method is no longer static. I also assume that events you are trying to subscribe to are events that follow .NET conventions (sender + event args). This way, we can leverage contravariance and always pass a lambda of type :

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

这篇关于为什么我动态创建的事件处理程序时,我得到一个参数异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆