简体   繁体   中英

Pass extra parameter to event with reflection

I am using reflection to bind events from webcontrols to my own methods. This is a generic function so I don't know the type of control or event in advance, but the events are for instance clicks (button) or selectedIndexChanged (dropdownlist). My function looks like this:

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

I need to know which event triggered MyEvent by passing in an extra parameter (see below). This is important because every webcontrol can have many events calling 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) { }

I am not allowed having different signatures when creating the delegate, the code only works when removing the last parameter string eventName . I have tried a workaround by setting eventName as default parameter. I have also tried subclassing EventArgs, but I am not permitted doing any change to the standard signature. I could possibly override the control events to adapt to my signature but I think there must be a simpler way.

Is there any way I can pass this extra parameter to the function when using reflection?

This does the trick, although it's not very pretty:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM