是否已添加事件处理程序?

有没有办法告诉如果一个事件处理程序已被添加到一个对象? 我序列化进出会话状态的对象列表,所以我们可以使用基于SQL的会话状态…当列表中的对象有一个属性发生了变化,它需要被标记,事件处理程序正确照顾之前。 但是,现在当对象被反序列化时,它并没有得到事件处理程序。

在一个温和的烦恼,我只是添加了事件处理程序访问该对象的Get属性。 它现在被调用,这是伟大的,除了它被调用了5次,所以我认为每次访问对象时,处理程序只是不断增加。

这是非常安全的,只是忽略,但我宁愿让它更清洁,检查是否已经添加处理程序,所以我只做一次。

那可能吗?

编辑:我不一定完全控制什么事件处理程序添加,所以只是检查null是不够的。

从@Telos提到的定义类之外,你只能在+=或者-=的左边使用EventHandler。 因此,如果您有修改定义类的能力,您可以通过检查事件处理程序是否为null来提供执行检查的方法 – 如果是,则不添加事件处理程序。 如果没有,那么也许你可以循环Delegate.GetInvocationList中的值。 如果其中一个与您想要作为事件处理程序添加的代理相同,则您知道它在那里。

 public bool IsEventHandlerRegistered(Delegate prospectiveHandler) { if ( this.EventHandler != null ) { foreach ( Delegate existingHandler in this.EventHandler.GetInvocationList() ) { if ( existingHandler == prospectiveHandler ) { return true; } } } return false; } 

这可以很容易地修改成“添加处理程序,如果它不存在”。 如果您无法访问暴露事件的内部课程,您可能需要根据@Lou Franco的build议探索-=+=

但是,重新审视debugging和停用这些对象的方式,看看您是否找不到自己追踪这些信息的方法。

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

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

请注意,每次注册处理程序时都要这样做,以确保您的处理程序只注册一次。 听起来像一个很好的做法,我:)

如果这是唯一的处理程序,则可以检查该事件是否为空,如果不是,则添加该处理程序。

我认为你可以在你的处理程序中安全地调用 – =事件,即使它没有被添加(如果没有,你可以捕获它) – 确保在添加之前它不在那里。

此示例显示如何使用方法GetInvocationList()将代理检索到已添加的所有处理程序。 如果您正在查看是否添加了特定的处理函数(函数),那么您可以使用数组。

 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属性中的各种属性,以查看是否添加了特定function。

如果你正在查看是否只有一个附加,你可以testing为空。

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

如果你不担心这一点,那么保持对事件处理程序的引用应该足够好。 如果担心其他对象丢失事件处理程序的副作用,则可能需要重新考虑caching策略。

我同意阿尔夫的答案,但对它的一点修改是,使用,

  try { control_name.Click -= event_Click; main_browser.Document.Click += Document_Click; } catch(Exception exce) { main_browser.Document.Click += Document_Click; } 
 EventHandler.GetInvocationList().Length > 0