C# 使用反射将事件处理程序绑定到任何类型的事件

C# 使用反射将事件处理程序绑定到任何类型的事件,c#,.net,events,C#,.net,Events,我有一些代码需要将事件动态绑定到事件处理程序: foreach (string evnt in attribute.Events) { EventInfo ei = control.GetType().GetEvent(evnt); if(ei != null) { ei.AddEventHandler(control, new EventHandler((s, e) => { // More awesomen

我有一些代码需要将事件动态绑定到事件处理程序:

foreach (string evnt in attribute.Events)
{
    EventInfo ei = control.GetType().GetEvent(evnt);
    if(ei != null)
    {
        ei.AddEventHandler(control, new EventHandler((s, e) =>
        {
            // More awesomeness here...
        }));
    }
}
var event_handler = new EventHandler((s, args) =>
{
    // More awesomeness here...
});
因此,对于事件列表中的每个字符串,从控件中获取事件并绑定一个处理程序

问题在于并非所有事件都是
EventHandler
,例如,一些事件可能是
KeyEventHander
MouseEventHandler

我不想要大量的if/else列表
EventHandler
派生类型,我只想绑定同一个处理程序,不管它是什么类型的
EventHandler


我怎样才能做到这一点?

这里有一种方法:

首先创建此帮助器类:

public class HandlerHelper<T> where T : EventArgs
{
    private readonly EventHandler m_HandlerToCall;

    public HandlerHelper(EventHandler handler_to_call)
    {
        m_HandlerToCall = handler_to_call;
    }

    public void Handle(object sender, T args)
    {
        m_HandlerToCall.Invoke(sender, args);
    }
}
下面是如何使用helper类为将调用
事件处理程序的不同事件处理程序类型创建不同委托的方法:

foreach (var event_name in event_names)
{
    var event_info = control.GetType().GetEvent(event_name);

    var event_handler_type = event_info.EventHandlerType;

    var event_args_type = event_handler_type.GetMethod("Invoke").GetParameters()[1].ParameterType;

    var helper_type = typeof(HandlerHelper<>).MakeGenericType(event_args_type);

    var helper = Activator.CreateInstance(helper_type, event_handler);

    Delegate my_delegate = Delegate.CreateDelegate(event_handler_type, helper, "Handle");

    event_info.AddEventHandler(button, my_delegate);
}
现在,我们使用
Delegate.CreateDelegate
为我们创建的特定
HandlerHelper
对象基于
handler
方法创建一个委托,并将该委托交给
AddEventHandler
方法


出于性能原因,您可以基于
事件参数类型

缓存委托(而不是每次创建一个委托)。您可以使用动态关键字附加处理程序。您可以在此处找到更多解释:

您当前拥有的有什么问题?@YacoubMassad-exception…类型为“System.EventHandler”的对象无法转换为类型为“System.Windows.Forms.KeyEventHandler”。@YacoubMassad基本上我需要表达式(s,e)=>{…}来应用于任何EventHander派生类型。在这种情况下,您不能;如果事件名称是
字符串
(请参阅问题中的
evnt
),则不适用。
dynamic
关键字在这里没有任何帮助。你链接到的文章与“动态关键字”毫无关系。谢谢,@marcGraveli有一个错误:Type helper=typeof(handlehalper)。MakeGenericType(typeof(MouseEventArgs));提供的泛型参数的数量不等于泛型类型定义的arity。非常奇怪。我在发布之前测试了这段代码。您是否按原样复制了把手?它只有一个泛型参数,我们正在将一个类型传递给
MakeGenericType
。这很奇怪。我将HandleHelper类复制到一个控制台应用程序中,并使用类型t=typeof(HandleHelper)进行测试;。。。。。工作得很好-然后在我的另一个解决方案中它就死了!。。。出于某种原因,它不喜欢HandleHelper是嵌套类!:-这可能就是我出错的地方
void Handle(object sender, MouseEventArgs args)