3

如果我有一个从 EventArgs 继承的类型(我们称之为 EventArgs1),还有一堆从 EventArgs1 继承的类(我们统称为 EventArgsX),然后是一堆类型的事件EventHandler<EventArgsX>,如果在运行时我通过了其中一个事件的 EventInfo,我想添加一个事件处理程序,该处理程序需要 EventArgs1 类型的第二个参数(例如MyEventHandler(object sender, EventArgs1 e))我该怎么做?

如果事件是类型,EventHandler<EventArgs1>那么我会这样做:

eventInfo.AddEventHandler(this, new EventHandler<EventArgs1>(MyEventHandler));

但是,当事件是 type 时,这会引发异常EventHandler<EventArgsX>,并且由于我在编译时不知道 EventArgsX 是什么,因此我不能简单地新建一个EventHandler<EventArgsX> 如果我确实知道在编译时将处理程序添加到哪个事件,那么这个完全可以接受:

MyEvent += MyEventHandler

但我根本不知道如何在运行时执行此操作。有什么建议么?

4

2 回答 2

4

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

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

var eventInfo = …;

EventHandler<EventArgs1> badHandler = MyEventHandler;

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

eventInfo.AddEventHandler(this, goodHandler);
于 2012-04-19T22:20:19.013 回答
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 实例。将导致运行时异常。实际上,当您添加委托时会捕获不匹配,因此会引发异常。

于 2012-04-19T22:19:52.917 回答