一尘不染

C#如何查找是否挂接事件

c#

我希望能够确定事件是否已挂断。我环顾四周,但只发现了涉及修改包含事件的对象内部的解决方案。我不想这么做

这是一些我认为可行的测试代码:

// Create a new event handler that takes in the function I want to execute when the event fires
EventHandler myEventHandler = new EventHandler(myObject_SomeEvent);
// Get "p1" number events that got hooked up to myEventHandler
int p1 = myEventHandler.GetInvocationList().Length;
// Now actually hook an event up
myObject.SomeEvent += m_myEventHandler;
// Re check "p2" number of events hooked up to myEventHandler
int p2 = myEventHandler.GetInvocationList().Length;

上面的不幸是完全错误的。我以为以某种方式将事件挂接到myEventHandler中的“
invocationList”会自动更新。但是,不是这样。它的长度总是归为一。

无论如何,是否可以从包含该事件的对象外部确定这一点?


阅读 395

收藏
2020-05-19

共1个答案

一尘不染

C#event关键字呈现一种微妙的错觉,即一个事件具有一个调用列表。

如果使用C#event关键字声明事件,则编译器将在您的类中生成一个私有委托,并为您管理它。每当您订阅事件时,add都会调用编译器生成的方法,该方法会将事件处理程序追加到委托的调用列表中。没有该事件的显式调用列表。

因此,获得委托人的调用列表的唯一方法是:

  • 使用反射来访问编译器生成的委托,或者
  • 创建一个非私有委托(也许是内部委托)并手动实现事件的添加/删除方法(这可防止编译器生成事件的默认实现)

这是演示后一种技术的示例。

class MyType
{
    internal EventHandler<int> _delegate;
    public event EventHandler<int> MyEvent;
    {
        add { _delegate += value; }
        remove { _delegate -= value; }
    }
}
2020-05-19