将额外参数传递给具有反射的事件

本文关键字:反射的 事件 参数传递 | 更新日期: 2023-09-27 17:59:52

我正在使用反射将Web控件中的事件绑定到我自己的方法。这是一个通用函数,所以我事先不知道控件或事件的类型,但事件是例如单击(按钮)或selectedIndexChanged(下拉列表)。我的功能如下:

protected void BindEvents(WebControl ctrl, string methodName, string eventType)
{
    System.Reflection.EventInfo eventInfo = ctrl.GetType().GetEvent(eventType);
    Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodName);
    eventInfo.AddEventHandler(ctrl, handler);
}

我需要通过传递一个额外的参数来知道是哪个事件触发了MyEvent(见下文)。这一点很重要,因为每个Web控件都可以有许多调用MyEvent的事件。

//1. Standard event signature
protected void Test_Click(object sender, EventArgs e) { } 
//2. Signature for my event
protected void MyEvent(object sender, EventArgs e, string eventName) { }

创建委托时不允许使用不同的签名,代码仅在删除最后一个参数string eventName时有效。我尝试了一种变通方法,将eventName设置为默认参数。我也尝试过对EventArgs进行子类化,但不允许对标准签名进行任何更改。我可能会覆盖控制事件以适应我的签名,但我认为必须有一个更简单的方法。

在使用反射时,有什么方法可以将这个额外的参数传递给函数吗?

将额外参数传递给具有反射的事件

这就成功了,尽管它不是很漂亮:

    protected void BindEvents(WebControl ctrl, string methodName, string eventType)
    {
        System.Reflection.EventInfo eventInfo = ctrl.GetType().GetEvent(eventType);
        var delegateType = eventInfo.EventHandlerType.GetMethod("Invoke");
        var methodInfo = this.GetType().GetMethod(methodName);
        var parameters = delegateType.GetParameters();
        if (parameters.Length!=2)
            throw new NotImplementedException(); // Can make switch and multiple CreateAction methods to handle
        var genericCreateAction = this.GetType().GetMethod("CreateAction2");
        var parameterTypes = parameters.Select(o => o.ParameterType).ToArray<Type>();
        var createAction = genericCreateAction.MakeGenericMethod(parameterTypes);
        var action = (Delegate)createAction.Invoke(this, new object[] { methodInfo, eventType });
        var properTypeAction = Delegate.CreateDelegate(eventInfo.EventHandlerType, action.Target, action.Method);
        eventInfo.AddEventHandler(ctrl, properTypeAction);
    }
    public Action<T1, T2> CreateAction2<T1, T2>(MethodInfo methodInfo, string eventName)
    {
        return (Action<T1, T2>)((p1, p2) => { methodInfo.Invoke(this, new object[] { p1, p2, eventName }); });
    }