有没有办法判断是否已将事件处理程序添加到对象中?我正在将对象列表序列化为进入/退出会话状态,因此我们可以使用基于SQL的会话状态...当列表中的对象更改了属性时,需要对其进行标记,事件处理程序在此之前正确处理。但是现在当对象被反序列化时,它没有得到事件处理程序。
在轻微的烦恼中,我只是将事件处理程序添加到访问该对象的Get属性中。它现在被调用了,这很好,除了它被调用了5次,所以我认为处理程序只是在每次访问对象时都会被添加。
真的很安全,只是忽略,但我宁愿通过检查处理程序是否已经添加来使它更清洁,所以我只这样做了一次。
这可能吗?
编辑:我不一定完全控制添加了什么事件处理程序,所以只检查null是不够的。答案 0 :(得分:177)
我最近遇到了类似的情况,我只需要为事件注册一次处理程序。我发现您可以先安全取消注册,然后再次注册,即使处理程序根本没有注册:
myClass.MyEvent -= MyHandler;
myClass.MyEvent += MyHandler;
请注意,每次注册处理程序时执行此操作都将确保您的处理程序只注册一次。 听起来对我来说是一个很好的做法:)
答案 1 :(得分:115)
在定义类之外,正如@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的建议探索-=
和+=
。
但是,您可能最好重新检查调试和停用这些对象的方式,看看您是否找不到自行跟踪此信息的方法。
答案 2 :(得分:18)
如果这是唯一的处理程序,您可以检查事件是否为null,如果不是,则添加处理程序。
我认为你可以安全地使用你的处理程序调用 - =即使它没有被添加(如果没有,你可以捕获它) - 确保它在添加之前不在那里。
答案 3 :(得分:6)
此示例显示如何使用方法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。
答案 4 :(得分:4)
如果我正确理解您的问题,您可能会遇到更大的问题。您说其他对象可能订阅这些事件。当对象被序列化和反序列化时,其他对象(您无法控制的对象)将丢失其事件处理程序。
如果你不担心,那么保持对你的事件处理程序的引用应该足够好了。如果您担心丢失事件处理程序的其他对象的副作用,那么您可能需要重新考虑缓存策略。
答案 5 :(得分:0)
EventHandler.GetInvocationList().Length > 0
答案 6 :(得分:0)
我同意alf的答案,但对它的修改很少, 使用,
try
{
control_name.Click -= event_Click;
main_browser.Document.Click += Document_Click;
}
catch(Exception exce)
{
main_browser.Document.Click += Document_Click;
}
答案 7 :(得分:0)
对我有用的唯一方法是创建一个布尔变量,添加事件时将其设置为true。然后我问:如果变量为false,则添加事件。
bool alreadyAdded = false;
此变量可以是全局变量。
if(!alreadyAdded)
{
myClass.MyEvent += MyHandler;
alreadyAdded = true;
}