我想设置一个事件处理程序,如果没有设置:
If GetHandlers(MyWindow.Closed, AddressOf MyWindow_Closed).Length = 0 Then
AddHandler MyWindow.Closed, AddressOf MyWindow_Closed
EndIf
答案 0 :(得分:2)
除了定义事件的代码之外,您无法真正查询事件委托的当前值。你的意图是什么?通常你不应该过于担心(必然)与其他订阅者?有一些方法可以通过封装来找到当前值,但是它们不推荐(这不是一个好主意)。
如果您关心的是您是否已经使用那个处理程序处理该事件(即您不想双重订阅,那么您始终可以:修复代码,以便它不会这样做,或b:作弊(C#示例):
// remove handler **if subscribed**, then re-subscribe
myWindow.Closed -= MyWindow_Closed;
myWindow.Closed += MyWindow_Closed;
要获得调用列表是......脆弱但可行。在简单的情况下,您可以使用反射来获取字段,并获取值。但是对于表单等,它使用稀疏技术(最小化没有订户的事件的空间)。如果是FormClosed
,则会通过EVENT_FORMCLOSED
键入。
使用示例(C#,抱歉)可能更有意义:
Form form = new Form();
form.FormClosed += delegate { Console.WriteLine("a");}; // just something, anything
form.FormClosed += delegate { Console.WriteLine("b");}; // just something, anything
object key = typeof(Form).GetField("EVENT_FORMCLOSED",
BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
EventHandlerList events = (EventHandlerList )
typeof(Component).GetProperty("Events",
BindingFlags.NonPublic | BindingFlags.Instance).GetValue(form, null);
FormClosedEventHandler handler = (FormClosedEventHandler)events[key];
foreach (FormClosedEventHandler subhandler in handler.GetInvocationList())
{
subhandler(form, null); // access the two events separately
}
对于ObservableCollection<T>
,委托直接在字段上,因此需要更少的间接:
ObservableCollection<SomeType> list = ...
NotifyCollectionChangedEventHandler handler = (NotifyCollectionChangedEventHandler)
list.GetType()
.GetField("CollectionChanged", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(list);