This question询问是否有办法查找代码是否已将自己的事件处理程序添加到事件中。但是,给出的答案只能在拥有该事件的同一个类中进行。 ( Delegate.GetInvocationList 和其他人。)
我想为 AppDomain.CurrentDomain.AssemblyResolve 添加自定义事件处理程序。有没有办法在再次添加之前找出我的自定义处理程序是否已添加? (对于此标准库事件和其他标准库事件。)
如果答案确实是'#34;那是不可能的。"那么请把它作为答案。
答案 0 :(得分:5)
那是不可能的。
基本上,您对外部事件的唯一操作是"订阅"和"取消订阅"。
现在,您可以在订阅前始终取消订阅。如果指定的处理程序不是事件的处理程序,则取消订阅是无操作。如果你确定总是这样做,那么你肯定只有一个处理程序订阅。这确实意味着你需要小心这样做你订阅的所有 - 所以理想情况下,将代码放在一个地方。
(或者,只需更改您的活动订阅,以便您可以轻松告诉您,您只会订阅一次...)
答案 1 :(得分:1)
你可以 ......
您可以使用反射来让所有代表订阅该活动,然后检查他们的名字,看看您的名字是否在那里......
public class Foo
{
public event EventHandler MyEvent;
}
public class Bar
{
public static event EventHandler MyStaticEvent;
}
public class Test
{
public void MyDelegate(object sender, EventArgs e) { }
}
class Program
{
static void Main(string[] args)
{
Foo aFoo = new Foo();
Test aTest = new Test();
aFoo.MyEvent += aTest.MyDelegate;
FieldInfo subscribersReflect = typeof(Foo).GetField("MyEvent", BindingFlags.NonPublic | BindingFlags.Instance);
Delegate[] subscribers = (subscribersReflect.GetValue(aFoo) as MulticastDelegate).GetInvocationList();
foreach (var sub in subscribers)
Console.WriteLine(sub.Method.Name); // MyDelegate
Bar.MyStaticEvent += aTest.MyDelegate;
subscribersReflect = typeof(Bar).GetField("MyStaticEvent", BindingFlags.NonPublic | BindingFlags.Static);
subscribers = (subscribersReflect.GetValue(null) as MulticastDelegate).GetInvocationList();
foreach (var sub in subscribers)
Console.WriteLine(sub.Method.Name); // MyDelegate
Console.ReadLine();
}
}
...但你真的不应该。
任何时候你发现自己想用反射去另一个班级挖掘,尤其是一个你没有来源的课程,而且超级特别是一个框架类,它应该是一个警告信号,表明你做错了。