Tutorial :C# - have method, need to remove or discover all events that reference it



Question:

I have a method that, throughout the lifetime of my app, gets added to any number of events. At some point I'd like to remove the method from all of the events that reference it. I only know the method...I would love to NOT keep a local List<EventHandler> of all the events the method gets added to because I think that somewhere/somehow the CLR is doing this for me for the purposes of garbage collection. Some pseudo-code below, any ideas? Thanks...

What I want to do:

public class Subscriber  {    public virtual void EventRaised(object pSender, EventArgs pArguments)    {      MessageBox.Show("EventRaised");    }      public virtual void UnsubscribeAll()    {      //Something like:      EventRaised.RemoveReferences();      //or      foreach(var MyReference in EventRaised.References)        MyReference.Remove();    }  }    var MySubscriber = new Subscriber();    ThisEvent += MySubscriber.EventRaised;  ThatEvent += MySubscriber.EventRaised;  //on and on...    MySubscriber.UnsubscribeAll();  

What I don't want to do:

public class Subscriber  {    protected List<EventHandler> Publishers = new List<EventHandler>();      public virtual void EventRaised(object pSender, EventArgs pArguments)    {      MessageBox.Show("EventRaised");    }      public virtual void Subscribe(EventHandler pPublisher)    {      pPublisher += EventRaised;      Publishers.Add(pPublisher);    }      public virtual void UnsubscribeAll()    {      foreach(var Publisher in Publishers)        Publisher -= EventRaised;        Publishers.Clear();    }  }    var MySubscriber = new Subscriber();    MySubscriber.Subscribe(ThisEvent);  MySubscriber.Subscribe(ThatEvent);  //on and on...    MySubscriber.UnsubscribeAll();  

Another Example

If the CLR doesn't keep track of the references per Stephen Cleary - bummer...that forces me into plan B. The answers and comments don't quite fit my problem - it's my fault though so I'll add another example below. JBall's code example #1 is very interesting and I'll add that to my bag of tricks.

I'm not removing the event references to the method with the need to or intention of restoring them later...I just want them gone. How about this pseudo-code - from the viewpoint of the Child, I want to say "forget whatever events my Parent attached to and attach to these events instead." I have several workarounds, including keeping a List<> of attached events, but I was hoping to leverage work that the CLR does for me behind-the-scenes. An added benefit of a CLR-maintained structure would've been the fact that it's definitive and final...there wouldn't have been a chance of attaching a method to an event without actually recording the reference.

public class Parent  {    public Parent()    {      AnObject.ThisEvent += EventRaised;      AnObject.ThatEvent += EventRaised;    }      public virtual void EventRaised(object pSender, EventArgs pArguments)    {      MessageBox.Show("EventRaised");    }  }    public class Child  {    public Child(): base()    {      //What I want to do:      EventRaised.RemoveAllEventReferences();        AnotherObject.ThisEvent += EventRaised;      AnotherObject.ThatEvent += EventRaised;    }  }  


Solution:1

Have your EventRaised method call another delegate which you by default assign, and when UnsubscribeAll() is called, remove that event from your inner delegate.

public class Subscriber  {      EventHander m_InnerEvent;        public Subscriber()      {          m_InnerEvent += InnerEventRaised;      }        public virtual void EventRaised(object pSender, EventArgs pArguments)      {          m_InnerEvent(pSender, pArguments);      }        protected virtual void InnerEventRaised(object pSender, EventArgs pArguments)      {          Console.WriteLine("EventRaised");      }        public virtual void UnsubscribeAll()      {          m_InnerEvent -= InnerEventRaised;      }  }  

Alternatively, have a flag that gets set when UnsubscribeAll() is called, and check that flag within your EventRaised method.

public class Subscriber  {      bool m_Active = true;        public virtual void EventRaised(object pSender, EventArgs pArguments)      {          if(m_Active) { InnerEventRaised(pSender, pArguments); }      }        void InnerEventRaised(object pSender, EventArgs pArguments)      {          Console.WriteLine("EventRaised");      }        public virtual void UnsubscribeAll()      {          m_Active = false;      }  }  

For your new example, if this is actually the structure of what you're trying to do, you simply need to refactor. Everything is happening in the constructors and the Child constructor is simply undoing what was done in the Parent constructor. Move the bits of the Parent constructor's actions into a method. Then the Child can override that method to skip what Parent would do and do what it wants instead:

public class Parent  {      public Parent()      {          AttachEventsToThings();      }        protected virtual void AttachEventsToThings()      {          AnObject.ThisEvent += EventRaised;          AnObject.ThatEvent += EventRaised;      }        public virtual void EventRaised(object pSender, EventArgs pArguments)      {          MessageBox.Show("EventRaised");      }  }    public class Child : Parent  {      protected override void AttachEventsToThings()      {          AnotherObject.ThisEvent += EventRaised;          AnotherObject.ThatEvent += EventRaised;      }  }  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »