有没有办法判断是否已将事件处理程序添加到对象中?我正在将对象列表序列化为进入/退出会话状态,因此我们可以使用基于SQL的会话状态...当列表中的对象更改了属性时,需要对其进行标记,事件处理程序在此之前正确处理.但是现在当对象被反序列化时,它没有得到事件处理程序.
在轻微的烦恼中,我刚刚将事件处理程序添加到访问该对象的Get属性中.它现在被调用,这很好,除了它被调用5次,所以我认为处理程序只是在每次访问对象时都会被添加.
它真的很安全,只是忽略,但我宁愿通过检查处理程序是否已被添加来使它更清洁,所以我只这样做了一次.
那可能吗?
编辑:我不一定完全控制添加什么事件处理程序,所以只检查null是不够的.
我最近遇到了类似的情况,我只需要为事件注册一次处理程序.我发现您可以先安全取消注册,然后再次注册,即使处理程序根本没有注册:
myClass.MyEvent -= MyHandler; myClass.MyEvent += MyHandler;
请注意,每次注册处理程序时执行此操作将确保您的处理程序只注册一次.听起来对我来说是一个很好的做法:)
从定义类的外部,如@Telos所提到的,你只能在a +=
或a 的左侧使用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的建议进行探索.
但是,您可能最好重新检查调试和停用这些对象的方式,看看您是否找不到自行跟踪此信息的方法.
如果这是唯一的处理程序,您可以检查事件是否为null,如果不是,则添加处理程序.
我认为您可以安全地使用您的处理程序调用 - =即使它没有添加(如果没有,您可以捕获它) - 确保它在添加之前不在那里.
此示例显示如何使用方法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属性上的各种属性,以查看是否已添加特定功能.
如果您正在查看是否只有一个附加,您可以只测试null.