How to determine if an event is signed

In my .NET application, I am subscribing to events from another class. Subscription is conditional. I subscribe to events when the control is visible and releases it when it becomes invisible. However, in some cases, I do not want to unsubscribe from the event, even if the control is not displayed, because I want the result of the operation that occurs in the background thread.

Is there a way through which I can determine if a class subscribed to this event?

I know that we can do this in a class that raises this event by checking the event for null , but how can I do this in a class that will subscribe to this event?

+42
c #
Apr 23 '10 at 8:45
source share
7 answers

The keyword event was explicitly invented so that you do not do what you want. It restricts access to the base delegate object, so no one can directly interact with subscribers to the event handlers that it stores. Events are accessories for the delegate, just as a property is an accessory for the field. The property allows only receiving and installing, the event only allows adding and removing.

This protects your code, and other code can only remove the event handler if it knows the event handler method and the target. C # language adds an extra layer of security by not letting you name the target.

And WinForms adds an extra layer of security, so it becomes difficult even if you use Reflection. It stores delegate instances in EventHandlerList with a secret cookie as a key, you need to know cookies in order to dig an object from the list.

Well, don’t go there. It is trivial to solve your problem with a little code at your end:

 private bool mSubscribed; private void Subscribe(bool enabled) { if (!enabled) textBox1.VisibleChanged -= textBox1_VisibleChanged; else if (!mSubscribed) textBox1.VisibleChanged += textBox1_VisibleChanged; mSubscribed = enabled; } 
+49
Apr 23 '10 at 10:07
source share

Assuming you don’t have access to the internal elements of the class that declare the event, you cannot do this directly. Events only expose the operators += and -= , nothing more. You will need a flag or some other mechanism in your subscription class to find out if you are signed or not.

+6
Apr 23 '10 at 8:59
source share
  /// <summary> /// Determine if a control has the event visible subscribed to /// </summary> /// <param name="controlObject">The control to look for the VisibleChanged event</param> /// <returns>True if the control is subscribed to a VisibleChanged event, False otherwise</returns> private bool IsSubscribed(Control controlObject) { FieldInfo event_visible_field_info = typeof(Control).GetField("EventVisible", BindingFlags.Static | BindingFlags.NonPublic); object object_value = event_visible_field_info.GetValue(controlObject); PropertyInfo events_property_info = controlObject.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance); EventHandlerList event_list = (EventHandlerList)events_property_info.GetValue(controlObject, null); return (event_list[object_value] != null); } 
+2
Apr 23 '10 at 12:10
source share

Can you put decision logic in a method that fires an event? Assuming you are using Winforms, it looks something like this:

  if (MyEvent != null && isCriteriaFulfilled) { MyEvent(); } 

Where isCriteriaFulfilled determined by your visible / invisible logic.

// UPDATES /////

In addition to your 1st comment, it would be inappropriate to change the behavior inside the event handler depending on the value of this.Visible ?

  a.Delegate += new Delegate(method1); ... private void method1() { if (this.Visible) // Do Stuff } 

Or if you really need to subscribe and unsubscribe:

  private Delegate _method1 = null; ... if(this.visible) { if (_method1 == null) _method1 = new Delegate(method1); a.Delegate += _method1; } else if (_method1 != null) { a.Delegate -= _method1; } 
+1
Apr 23 '10 at 9:11
source share

Just check if the control is displayed or not when the event handler starts.

+1
Apr 23 '10 at 9:24
source share

Don't you remember if you signed? This approach has worked for me so far. Even if you have many events or objects, you can still just remember this (for example, in a dictionary).

On the other hand, changing visibility was, at least for me, not very good for subscribing / unsubscribing. I usually prefer Building / Disposed, which are more understandable than every time visibility changes.

0
Apr 23 2018-10-10T00:
source share

I am just expanding Hans answer. I'm just trying to ensure that I do not install my handler more than once, and do not remove it when I still need it. This does not protect against an improper call by an attacker or an attacker, since you will need to keep track of callers, and it will simply open you up for re-subscriptions to intercept the tracking mechanism.

 // Tracks how many times the ReflectionOnlyResolveHandler has been requested. private static int _subscribers = 0; /// <summary> /// Register or unregister the ReflectionOnlyResolveHandler. /// </summary> /// <param name="enable"></param> public static void SubscribeReflectionOnlyResolve(bool enable) { lock(_lock) { if (_subscribers > 0 && !enable) _subscribers -= 1; else if (enable) _subscribers += 1; if (enable && _subscribers == 1) AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ReflectionHelper.ReflectionOnlyResolveHandler; else if (_subscribers == 0) AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= ReflectionHelper.ReflectionOnlyResolveHandler; } } 
0
Jul 15 '16 at 21:14
source share



All Articles