如何在运行时向事件添加更通用的事件处理程序
本文关键字:事件处理 程序 添加 运行时 事件 | 更新日期: 2023-09-27 18:31:37
类(让我们将它们统称为 EventArgsX),然后是一堆类型为 EventHandler<EventArgsX>
的事件,如果在运行时我被传递给这些事件之一的 EventInfo,并且我想添加一个需要 EventArgs1 类型的第二个参数的事件处理程序(例如 MyEventHandler(object sender, EventArgs1 e)
) 我该怎么做?
如果事件是 EventHandler<EventArgs1>
类型,那么我将这样做:
eventInfo.AddEventHandler(this, new EventHandler<EventArgs1>(MyEventHandler));
但是当事件类型为 EventHandler<EventArgsX>
时,这会引发异常,并且由于我不知道编译时的 EventArgsX 是什么,因此我不能简单地新建一个EventHandler<EventArgsX>
如果我确实知道我在编译时将处理程序添加到哪个事件,那么这将是完全可以接受的:
MyEvent += MyEventHandler
但我根本无法弄清楚如何在运行时执行此操作。有什么建议吗?
我不能简单地重新建立
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);
更新
基本上,我已经倒着读了这个问题;我将留下这个答案,以防其他试图做相反事情的人发现这个问题。
基本上,你不能做你想做的事情。 如果委托的 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 实例。 将导致运行时异常。 实际上,当您添加委托时会捕获不匹配,因此会引发异常。