[英]Binding an event handler to any type of event using reflection
I have some code where I need to dynamically bind events to an event handler: 我有一些代码,我需要动态绑定事件到事件处理程序:
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...
}));
}
}
So for each string in the event list, get the event from the control and bind a handler. 因此,对于事件列表中的每个字符串,从控件获取事件并绑定处理程序。
The problem is that not all events are EventHandler
, some for example might be KeyEventHander
or MouseEventHandler
etc. 问题是并非所有事件都是
EventHandler
,例如某些EventHandler
可能是KeyEventHander
或MouseEventHandler
等。
I don't want a massive if/else list of EventHandler
derived types, I just want to bind the same handler regardless of what type of EventHandler
it is. 我不想要一个大量的if / else列表的
EventHandler
派生类型,我只想绑定相同的处理程序,无论它是什么类型的EventHandler
。
How can I do this? 我怎样才能做到这一点?
Here is one way to do it: 这是一种方法:
First create this helper class: 首先创建这个助手类:
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);
}
}
This generic class has a Handle
method that will be used to be our delegate for the many event handler types. 这个泛型类有一个
Handle
方法,它将用作许多事件处理程序类型的委托。 Note that this class is generic. 请注意,此类是通用的。
T
will be one of the many EventArgs
derived classes for different event types. T
将是针对不同事件类型的许多EventArgs
派生类之一。
Now let's say you define the following event handler: 现在假设你定义了以下事件处理程序:
var event_handler = new EventHandler((s, args) =>
{
// More awesomeness here...
});
Here is how you can use the helper class to create different delegates for the different event handler types that will invoke event_handler
: 以下是如何使用helper类为将调用
event_handler
的不同事件处理程序类型创建不同的委托:
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);
}
For each event, we obtain the EventHandlerType
which is like EventHandler
or MouseEventHandler
. 对于每个事件,我们获取
EventHandlerType
,它类似于EventHandler
或MouseEventHandler
。
Then we use reflection to get the type of the second parameter which is like EventArgs
or MouseEventArgs
. 然后我们使用反射来获取第二个参数的类型,如
EventArgs
或MouseEventArgs
。
Then we create an instance of HandlerHelper<>
based on the type of the EventArgs
parameter. 然后我们根据
EventArgs
参数的类型创建一个HandlerHelper<>
实例。 For example HandlerHelper<EventArgs>
or HandlerHelper<MouseEventArgs>
. 例如
HandlerHelper<EventArgs>
或HandlerHelper<MouseEventArgs>
。
We give event_handler
to the constructor of HandlerHelper
so that it can call it when it's Handle
method is invoked. 我们给
event_handler
到的构造HandlerHelper
,以便它可以调用它时,它的Handle
方法被调用。
This makes the signature of the Handle
method as we want. 这使得
Handle
方法的签名成为我们想要的。 For example, in the case of HandlerHelper<MouseEventArgs>
, the signature of the Handle
method is: 例如,在
HandlerHelper<MouseEventArgs>
的情况下, Handle
方法的签名是:
void Handle(object sender, MouseEventArgs args)
Now, we use Delegate.CreateDelegate
to create a delegate based on the Handle
method for the specific HandlerHelper
object that we created, and we give such delegate to the AddEventHandler
method. 现在,我们使用
Delegate.CreateDelegate
基于我们创建的特定HandlerHelper
对象的Handle
方法创建委托,并将这样的委托给予AddEventHandler
方法。
For performance reasons, you can cache the delegate (instead of creating one every time) based on event_args_type
. 出于性能原因,您可以基于
event_args_type
缓存委托(而不是每次创建一个委托)。
You can use dynamic key word to attach the handler. 您可以使用动态关键字来附加处理程序。 More explanation you can find here: https://msdn.microsoft.com/en-us/library/ms228976(v=vs.110).aspx
您可以在此处找到更多解释: https : //msdn.microsoft.com/en-us/library/ms228976(v = vs.110).aspx
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.