如何在运行时向事件添加更通用的事件处理程序

时间:2012-04-19 20:25:05

标签: c# .net events delegates

如果我有一个继承自EventArgs的类型(让我们称之为EventArgs1),还有一大堆继承自EventArgs1的类(让我们将它们统称为EventArgsX),然后是一堆类型为{的事件{1}},如果在运行时我传递了其中一个事件的EventInfo,并且我想添加一个事件处理程序,它需要第二个类型为EventArgs1的参数(例如EventHandler<EventArgsX>)我该怎么做?

如果事件的类型为MyEventHandler(object sender, EventArgs1 e),那么我会这样做:

EventHandler<EventArgs1>

但是当事件的类型为eventInfo.AddEventHandler(this, new EventHandler<EventArgs1>(MyEventHandler)); 时会抛出异常,因为我不知道编译时EventArgsX是什么,所以我不能简单地新建一个EventHandler<EventArgsX>如果我知道的话我在编译时添加处理程序的事件然后这是完全可以接受的:

EventHandler<EventArgsX>

但我无法弄清楚如何在运行时执行此操作。有什么建议吗?

2 个答案:

答案 0 :(得分:4)

  

我不能简单地新建一个EventHandler<EventArgsX>

当然可以,尽管你需要使用Delegate.CreateDelegate()和反射来做到这一点。假设MyEventHandlerthis上的实例方法,您可以这样做:

var eventInfo = …;

EventHandler<EventArgs1> badHandler = MyEventHandler;

var goodHandler = Delegate.CreateDelegate(
    eventInfo.EventHandlerType, this, badHandler.Method);

eventInfo.AddEventHandler(this, goodHandler);

答案 1 :(得分:0)

<强>更新

我基本上已经向后看了这个问题;我会留下这个答案,以防其他 尝试反向的人发现这个问题。


基本上,你不能做你想做的事。如果委托的EventArgs类型是事件声明类型的子类,则事件无法添加委托。当输入参数是逆变时,你试图使用协方差。

假设这些类

class EventArgs1 : EventArgs {}
class EventArgsA : EventArgs1 {}
class EventArgsB : EventArgs1 {}

如果您可以将方法void Handle(object sender, EventArgsA args)添加到签名为void SomeEvent(object sender, EventArgs1 args)的事件中,会发生什么情况。事件源可能会这样做:

if (SomeEvent != null)
{
    var args = new EventArgsB();
    SomeEvent(this, args);      //this line is perfectly legal, as EventArgsB inherits from EventArgs1.
}

但是,当运行时在事件的调用列表中到达此委托时,它现在必须将args对象传递给Handle(object, EventArgsA),它当然不能这样做,因为EventArgsB实例不是EventArgsA实例。将导致运行时异常。实际上,添加委托时会捕获不匹配,因此抛出异常。