是否有一种方法可以判断事件处理程序是否已添加到对象?我正在序列化一个对象列表进入/退出会话状态,这样我们就可以使用基于SQL的会话状态…当列表中的对象发生属性更改时,需要标记它,这是事件处理程序之前适当处理的。但是现在当对象被反序列化时,它不会得到事件处理程序。

出于些许烦恼,我只是将事件处理程序添加到访问对象的Get属性中。它现在被调用了,这很好,除了它被调用了5次所以我认为每次对象被访问时处理程序都会被添加。

忽略它确实足够安全,但我宁愿通过检查是否已经添加了处理程序来使它更干净,因此我只这样做一次。

这可能吗?

编辑:我没有必要完全控制添加什么事件处理程序,所以仅仅检查null是不够的。


当前回答

这个例子展示了如何使用GetInvocationList()方法来检索已添加的所有处理程序的委托。如果要查看是否添加了特定的处理程序(函数),则可以使用array。

public class MyClass
{
  event Action MyEvent;
}

...

MyClass myClass = new MyClass();
myClass.MyEvent += SomeFunction;

...

Action[] handlers = myClass.MyEvent.GetInvocationList(); //this will be an array of 1 in this example

Console.WriteLine(handlers[0].Method.Name);//prints the name of the method

您可以检查委托的Method属性上的各种属性,以查看是否添加了特定的函数。

如果您要查看是否只有一个附加,您可以只测试为空。

其他回答

这个例子展示了如何使用GetInvocationList()方法来检索已添加的所有处理程序的委托。如果要查看是否添加了特定的处理程序(函数),则可以使用array。

public class MyClass
{
  event Action MyEvent;
}

...

MyClass myClass = new MyClass();
myClass.MyEvent += SomeFunction;

...

Action[] handlers = myClass.MyEvent.GetInvocationList(); //this will be an array of 1 in this example

Console.WriteLine(handlers[0].Method.Name);//prints the name of the method

您可以检查委托的Method属性上的各种属性,以查看是否添加了特定的函数。

如果您要查看是否只有一个附加,您可以只测试为空。

EventHandler.GetInvocationList().Length > 0

我同意阿尔夫的回答,但稍加修改, 使用,

           try
            {
                control_name.Click -= event_Click;
                main_browser.Document.Click += Document_Click;
            }
            catch(Exception exce)
            {
                main_browser.Document.Click += Document_Click;
            }

如果我对你的问题理解正确,你可能有更大的问题。你说过其他对象可能订阅这些事件。当对象被序列化和反序列化时,其他对象(您无法控制的对象)将失去它们的事件处理程序。

如果您不担心这个问题,那么保持对事件处理程序的引用就足够了。如果您担心其他对象丢失其事件处理程序的副作用,那么您可能需要重新考虑缓存策略。

我最近遇到了类似的情况,我只需要为一个事件注册一次处理程序。我发现你可以安全地先注销,然后再次注册,即使处理程序根本没有注册:

myClass.MyEvent -= MyHandler;
myClass.MyEvent += MyHandler;

请注意,每次注册处理程序时都这样做将确保处理程序只注册一次。 听起来对我来说是一个很好的练习:)