【发布时间】:2010-01-25 07:08:14
【问题描述】:
我只想在未设置的情况下设置事件处理程序:
If GetHandlers(MyWindow.Closed, AddressOf MyWindow_Closed).Length = 0 Then
AddHandler MyWindow.Closed, AddressOf MyWindow_Closed
EndIf
【问题讨论】:
标签: vb.net delegates event-handling
我只想在未设置的情况下设置事件处理程序:
If GetHandlers(MyWindow.Closed, AddressOf MyWindow_Closed).Length = 0 Then
AddHandler MyWindow.Closed, AddressOf MyWindow_Closed
EndIf
【问题讨论】:
标签: vb.net delegates event-handling
您无法真正查询事件委托的当前值,除非在定义事件的代码中。你在这里的意图是什么?通常你不应该(不必要地)太关心其他订阅者吗?有一些方法可以破解封装以找到当前值,但不推荐使用它们(这不是一个好主意)。
如果您关心的是您是否已经在使用 that 处理程序处理该事件(即您不想重复订阅,那么您可以随时选择:修复代码,使其不会t 这样做,或者 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);
【讨论】:
INotifyCollectionChanged 的是什么?