locked
How can I iterate through the list of methods subscribed to any event?

    Question

  • Say, if I've a button1's click event and if I'm subscribing two methods to this click event...

    Later on, in some other button2's click event, I would like to iterate through the list of methods subscribed to button1's click event...

    How can I do this?

    Thanks & Regards
    Trinadh P.
    |\||\|\||
    Saturday, June 07, 2008 3:57 AM

Answers

  •  You can't enumerate the subscribers of an event from outside of the class contained in the event.  The event keyword causes two methods to be created: add and remove for the event--nothing else.  There's no way to get at the multicast delegate from outside the class.  From inside the class you can use the GetInvocationList method on the event delegate (if there is one).
    http://www.peterRitchie.com/blog
    • Marked as answer by jack 321 Wednesday, June 11, 2008 5:50 AM
    Monday, June 09, 2008 8:25 PM
  • Peter, aren't all "events" delegates (or multicastdelegates, to be precise)?  One blogger has categorize the C# "event" and"delegate" keywords as "sugar coating" for the MulticastDelegate class.  From experience, the Button control 's CLICK event is restricted so that you can't get at the underlying multicast.  I suspect all MS standard controls are restricted this way.  In fact, I suspect all events are restricted outside of the class in which they are defined.  But, if you implement your own events, then your class has access to the multicast via a type cast...

    MulticastDelegate m = (MulticastDelegate)myEvent;  
     
    //Then you can get the delegate list...  
     
    Delegate [] dlist = m.GetInvocationList();  
     
    //and then iterate through to find and invoke the ones you want...  
     
    foreach(Delegate d in dlist)  
    {  
        if(aListOfObjects.Contains(d.Target))  
        {  
            object [] p = { /*put your parameters here*/ };  
            d.DynamicInvoke(p);  
        }  
        else  
            MessageBox.Show("Not Invoking the Event for " + d.Target.ToString() + ":" + d.Target.GetHashCode().ToString());  
    }  
     
     
    • Marked as answer by jack 321 Wednesday, June 11, 2008 5:51 AM
    • Edited by xalnix Friday, September 12, 2008 10:05 PM fix typo
    Monday, June 09, 2008 9:27 PM

All replies

  • The Button Click event can only be the left-hand-side of a += or -=, so querying it directly may not be possible.  You could create a MulticastDelegate object, add your button click event handers to that and then use GetInvokationList() to list the delegates to add to the click event (at initialization time) and to query for the delegates currently attached to Click.  You could also use the list to remove the delegates from click.

    • Proposed as answer by xalnix Sunday, June 08, 2008 1:28 PM
    Saturday, June 07, 2008 11:41 AM
  •  You can't enumerate the subscribers of an event from outside of the class contained in the event.  The event keyword causes two methods to be created: add and remove for the event--nothing else.  There's no way to get at the multicast delegate from outside the class.  From inside the class you can use the GetInvocationList method on the event delegate (if there is one).
    http://www.peterRitchie.com/blog
    • Marked as answer by jack 321 Wednesday, June 11, 2008 5:50 AM
    Monday, June 09, 2008 8:25 PM
  • Peter, aren't all "events" delegates (or multicastdelegates, to be precise)?  One blogger has categorize the C# "event" and"delegate" keywords as "sugar coating" for the MulticastDelegate class.  From experience, the Button control 's CLICK event is restricted so that you can't get at the underlying multicast.  I suspect all MS standard controls are restricted this way.  In fact, I suspect all events are restricted outside of the class in which they are defined.  But, if you implement your own events, then your class has access to the multicast via a type cast...

    MulticastDelegate m = (MulticastDelegate)myEvent;  
     
    //Then you can get the delegate list...  
     
    Delegate [] dlist = m.GetInvocationList();  
     
    //and then iterate through to find and invoke the ones you want...  
     
    foreach(Delegate d in dlist)  
    {  
        if(aListOfObjects.Contains(d.Target))  
        {  
            object [] p = { /*put your parameters here*/ };  
            d.DynamicInvoke(p);  
        }  
        else  
            MessageBox.Show("Not Invoking the Event for " + d.Target.ToString() + ":" + d.Target.GetHashCode().ToString());  
    }  
     
     
    • Marked as answer by jack 321 Wednesday, June 11, 2008 5:51 AM
    • Edited by xalnix Friday, September 12, 2008 10:05 PM fix typo
    Monday, June 09, 2008 9:27 PM
  • TRID,
    Here's a great thread that might help you get there.  Since the problem is to get at "button1" click event, and since it can't be on the right hand side (from outside of the class where defined), the solution is complex.  But reflection might work as discussed and answered in topic "How to find registered event handlers?" in this forum, posted a few minutes ago.

    Monday, June 09, 2008 10:10 PM
  • xalnix said:

    Peter, aren't all "events" delegates (or multicastdelegates, to be precise)?  One blogger has categorize the C# "event" and"delegate" keywords as "sugar coating" for the MulticastDelegate class.  From experience, the Button control 's CLICK event is restricted so that you can't get at the underlying multicast.  I suspect all MS standard controls are restricted this way.  In fact, I suspect all events are restricted outside of the class in which the are defined.  But, if you implement your own events, then your class has access to the multicast via a type cast...

    MulticastDelegate m = (MulticastDelegate)myEvent;  
     
    //Then you can get the delegate list...  
     
    Delegate [] dlist = m.GetInvocationList();  
     
    //and then iterate through to find and invoke the ones you want...  
     
    foreach(Delegate d in dlist)  
    {  
        if(aListOfObjects.Contains(d.Target))  
        {  
            object [] p = { /*put your parameters here*/ };  
            d.DynamicInvoke(p);  
        }  
        else  
            MessageBox.Show("Not Invoking the Event for " + d.Target.ToString() + ":" + d.Target.GetHashCode().ToString());  
    }  
     
     



    Not all events are implemented as a delegate member.  The event keyword defaults to implementing events via a single multi-cast delegate, but you can override that.  For example:
            private EventHandlerList events = new EventHandlerList();  
            private Object myeventObject = new object();  
            public event EventHandler<EventArgs> myevent  
            {  
                add { events.AddHandler(myeventObject, value); }  
                remove { events.RemoveHandler(myeventObject, value); }  
            }  
     
    In this case, for another class to iterate all the methods subscribed to myevent, it would have to have access to the events member.  Another possibility is to override the event add/remove and only use non-multi-cast delegates (i.e. there would only be one subscriber at a time).
    http://www.peterRitchie.com/blog
    Tuesday, June 10, 2008 12:06 AM