Share via


How to know when an event is subscribed?

Question

Saturday, July 5, 2008 10:58 AM

 Hi,

I have a form with an own event, an I want to know when this event is subscribed by another object. Is there a way to do that?

Example:

public delegate void MyEventHandler();

public class MyClass

{  

    public event MyEventHandler HandleMe;

}

public class MySubscriber

{

    public void Subscribe(MyClass class

    {  

        class.HandleMe += HandleMe;

        // Here I want MyClass instance to know that

        // another object has binded to its event.

    }

    public void Form1_HandleMe()

    {

        // MyClass has raised the event

     }

}

Any help will be appreciated!

All replies (6)

Saturday, July 5, 2008 11:25 AM ✅Answered | 1 vote

You can do this by adding a property to the class handling the events...

    public bool HandlingEvent { get { return (HandleMe != null); } }

This line would be called by your Subscriber class to see if anyone has subscribed.

You could get fancier as follows...

        private event MyEventHandler _handleMe;  
        public event MyEventHandler HandleMe {  
            add { _handleMe += value; if(HandlingEvents) _handleMe(); }  
            remove { _handleMe -= value; }  
        }  
        public bool HandlingEvents { get { return (_handleMe != null); } }  
 

... now, not only can you query your class, the class will actually fire the event.  Move the firing of the event around to get the behavior you desire.

This is a very powerful feature but alas, you can't use it on a class you haven't defined.  For examply, you cannot take the stock "Button" control class and write similar code to get at its subscribers.  Only the Button implementation can access its event subscribers (not absolutely true, but very complex).


Saturday, July 5, 2008 3:39 PM ✅Answered | 1 vote

You can find out immediately by providing an explicit add/remove implementation:

private MyEventHandler handler;
public event MyEventHandler HandleMe {
  add {
    // somebody is adding!
    handler += value;
  }
  remove {
    // somebody is removing!
    handler -= value;
  }
}

When raising the event, you now need to check the private delegate (handler), not the event:

if(handler!=null) handler();

This is more-or-less what the compiler does automatically if you use the abbeviated event syntax.


Marc


Saturday, July 5, 2008 9:21 PM

Thank you both for the answer, I will work around on it.

I was thinking in something like overriding the oeprator+= and operator-=, but now I see that I can control this operators more acurately and smarter than I thought.


Sunday, July 6, 2008 3:11 AM

Actually from within the class that defines the event, you have a number of options like suggested keeping track your self if someone (un)subscribes or just check if the eventhandler is null.  A third option would be to check the invocation list of the event. the following sample shows the last two options.

1 using System;  
2  
3 namespace EventSubscriberTest  
4 {  
5     public delegate void MyEventHandler();   
6  
7     public static class Helpers  
8     {  
9         public static bool HasSubscribers_Type1(this Delegate handler)  
10         {  
11             if (handler != null)  
12             {  
13                 return (handler.GetInvocationList().Length) > 0;  
14             }  
15             return false;  
16         }  
17  
18         public static bool HasSubscribers_Type2(this Delegate handler)  
19         {  
20             return (handler != null);  
21         }  
22     }  
23  
24     public class MyClass   
25     {         
26         public event MyEventHandler HandleMe;  
27         public void FireHandleMe()  
28         {  
29             MyEventHandler handler = HandleMe;  
30             if (handler != null)  
31             {  
32                 handler();  
33             }  
34         }  
35  
36         //This has to be defined in the class that defines the   
37         //event because outside of the defining class only  
38         //the += and -= operators are allowed on events.  
39         public bool HandleMeHasSubscribers_Type1  
40         {  
41             get 
42             {  
43                 return HandleMe.HasSubscribers_Type1();  
44             }  
45         }  
46  
47         public bool HandleMeHasSubscribers_Type2  
48         {  
49             get 
50             {  
51                 return HandleMe.HasSubscribers_Type2();  
52             }  
53         }  
54     }    
55       
56     public class MySubscriber   
57     {       
58         public void Subscribe(MyClass obj)  
59         {  
60             if (obj.HandleMeHasSubscribers_Type1)  
61             {  
62                 Console.WriteLine("HandleMe already has a subscriber, Not Subscribing");  
63                 //Do alternative logic here.  
64             }  
65             else 
66             {  
67                 Console.WriteLine("HandleMe has no subscribers, Subscribing");  
68                 obj.HandleMe += HandleMe; // Here I want MyClass instance to know that           
69                                           // another object has binded to its event.       
70             }  
71         }       
72  
73         public void HandleMe()       
74         {  
75             Console.WriteLine("Handle me executed");  
76         }   
77     }   
78  
79     class Program  
80     {  
81         static void Main(string[] args)  
82         {  
83             MyClass myclass = new MyClass();  
84             MySubscriber sub = new MySubscriber();  
85             //Subscribe  
86             sub.Subscribe(myclass);  
87             //Subscribe again  
88             sub.Subscribe(myclass);  
89             //Trigger the event  
90             myclass.FireHandleMe();  
91         }  
92     }  
93 }  
94  

I put the implementation in a helper class as extention methods to keep the code nice and reusable for other events.


Sunday, July 6, 2008 9:22 AM

Re checking the invocation list > 0, this is unnecessary; if there are zero targets, the delegate instance itself will be null due to how Delegate.Remove works.


Marc


Tuesday, July 8, 2008 11:38 AM

Hi Ray

I think your post is a bit confusing, when having the option of use events as properties. Subscribing would not follow the traditional event binding (operator+= and operator-=).

But thanks for reply.