开发者

AddHandler only if no handlers for this event?

I want to set an event handler only if this is not set:

If GetHandlers(MyWindow.Closed开发者_如何学编程, AddressOf MyWindow_Closed).Length = 0 Then
    AddHandler MyWindow.Closed, AddressOf MyWindow_Closed
EndIf


You can't really query the current value of the event's delegate, except in the code that defines the event. What is your intent here? Normally you shouldn't be too concerned (necessarily) with other subscribers? There are ways of hacking past the encapsulation to find the current value, but they are not recommended (it just isn't a good idea).

If your concern is whether you are already handling that event with that handler (i.e. you don't want to double-subscribe, then you can always either a: fix the code so it doesn't do this, or b: cheat (C# example):

// remove handler **if subscribed**, then re-subscribe
myWindow.Closed -= MyWindow_Closed;
myWindow.Closed += MyWindow_Closed;

To get the invocation list is... brittle but doable. In simple cases you can just use reflection to get the field, and snag the value. But with forms etc it uses sparse techniques (to minimise the space for events without subscribers). In the case of FormClosed, this is keyed via EVENT_FORMCLOSED.

It might make more sense with an example (C#, sorry):

    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
    }

In the case of an ObservableCollection<T>, the delegate is directly on a field, so less indirection is required:

ObservableCollection<SomeType> list = ...
NotifyCollectionChangedEventHandler handler = (NotifyCollectionChangedEventHandler)
    list.GetType()
    .GetField("CollectionChanged", BindingFlags.Instance | BindingFlags.NonPublic)
    .GetValue(list);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜