Clearing all event handler attached to an event

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?Utf-8?B?TmF2YW5lZXRoLksuTg==?=

    #1

    Clearing all event handler attached to an event

    Hi all,

    Recently I found an interesting question on C# forums about clearing event
    handlers of an event. I tried to give it a solution, but failed. I am
    interested to know how you guys take this. Here it goes

    class Product
    {
    public event EventHandler ProductChanged;

    public Product(string name) {
    this.name = name;
    }

    private string name;
    public string Name
    {
    get { return name; }
    set {
    name = value;
    if (ProductChanged != null)
    ProductChanged( this, EventArgs.Empty );
    }
    }
    }

    "ProductChanged " event will have many subscribers. I need to clear all these
    subscribers from outside "Product" class. Reason is, I am not allowed to
    change the "Product" class. I am attaching the event handlers like this,

    Product first = new Product("First product");
    first.ProductCh anged += new EventHandler(fi rst_ProductChan ged);

    Product second = new Product("Second product");
    second.ProductC hanged += new EventHandler(se cond_ProductCha nged);

    // need to clear the ProductChanged event handlers here
    // I can't get the invocation list of "Product.Produc tChanged" event here.

    is there anyway to achieve this? I think some kind of reflection can do
    that, but I am not sure how to go about it.

    Any help would be great
  • Peter Duniho

    #2
    Re: Clearing all event handler attached to an event

    On Mon, 20 Oct 2008 20:37:01 -0700, Navaneeth.K.N
    <NavaneethKN@di scussions.micro soft.comwrote:
    [...]
    // need to clear the ProductChanged event handlers here
    // I can't get the invocation list of "Product.Produc tChanged" event
    here.
    >
    is there anyway to achieve this? I think some kind of reflection can do
    that, but I am not sure how to go about it.
    Reflection would not be at all reliable. The field backing the event
    could be modified with reflection, but the name of the field could change
    at any time. Even if you could rely on the name, it's a _really_ bad idea
    to go around mucking about the internals of some class. If you're not
    allowed to modify the class itself to support what you want, then you
    definitely have no business poking around the class's internals. That's
    bad design and a maintenance nightmare.
    Any help would be great
    IMHO, the only correct way to do it is to keep your own list of all the
    delegates you've subscribed to the event, so that when you want to remove
    them all, you can do that.

    One way to effectively accomplish this is to actually duplicate the event
    yourself in your own class, subscribe a single event handler to the
    Product class, and then forward the event to your own event. When you
    want to clear your own event, you can just set it to null (from within the
    class declaring the event, where you are actually setting the event's
    delegate field to null).

    In your case, however, it looks like you want to apply this to the same
    event on multiple instances of the same type. So you'll need to combine
    the above approach with a convenient way to map each instance to the
    delegate used for the event. A Dictionary<inst ance can be used for that.

    For example (error-checking removed for clarity, uncompiled code):

    class MyClass
    {
    private Dictionary<Prod uct, EventHandler_di ctEventForwarde r =
    new Dictionary<Prod uct, EventHandler>() ;

    private void _Subscribe(Prod uct product, EventHandler handler)
    {
    EventHandler handlerOld;

    if (_dictEventForw arder.TryGetVal ue(product, out handlerOld))
    {
    handlerOld += handler;
    }
    else
    {
    handlerOld = handler;
    product.Product Changed += _ForwardingHand ler;
    }

    _dictEventForwa rder[product] = handlerOld;
    }

    private void _Unsubscribe(Pr oduct product, EventHandler handler)
    {
    EventHandler handlerNew = _dictEventHandl er[product] - handler;

    if (handlerNew == null)
    {
    _dictEventHandl er.Remove(produ ct);
    product.Product Changed -= _ForwardingHand ler;
    }
    else
    {
    _dictEventHandl er[product] = handlerNew;
    }
    }

    private void _Clear(Product product)
    {
    _dictEventHandl er.Remove(produ ct);
    product.Product Changed -= _ForwardingHand ler;
    }

    private void _ForwardingHand ler(object sender, EventArgs e)
    {
    _dictEventForwa rder[(Product)sender](sender, e);
    }
    }

    You'll note that to subscribe/unsubscribe handlers to the event, you need
    to go through the special methods for the purpose, rather than doing it
    directly. They wind up subscribing/unsubscribing a single method that
    looks up the appropriate delegate for each instance's event and invokes
    that delegate when the instance's event is raised.

    Hope that helps.

    Pete

    Comment

    • Israel

      #3
      Re: Clearing all event handler attached to an event

      On Oct 20, 11:37 pm, Navaneeth.K.N
      <Navaneet...@di scussions.micro soft.comwrote:
      "ProductChanged " event will have many subscribers. I need to clear all these
      subscribers from outside "Product" class. Reason is, I am not allowed to
      change the "Product" class. I am attaching the event handlers like this,
      Can you insert a proxy class that looks exactly like the Product class
      and contains a reference to it? Then you could manage your own
      delegate list via the standard add/remove methods and just subscribe
      to the Product event once and when Clear() is called just clear our
      your list and unsubscribe to the Product class's event. This would
      require that everyone go through the proxy vs. the Product class.


      Comment

      • =?Utf-8?B?TmF2YW5lZXRoLksuTg==?=

        #4
        Re: Clearing all event handler attached to an event

        Peter,

        That was a perfect answer. Thanks for that.

        BTW, will unregistered events won't get collected on GC cycles?

        Comment

        • Peter Duniho

          #5
          Re: Clearing all event handler attached to an event

          On Tue, 21 Oct 2008 11:18:22 -0700, Navaneeth.K.N
          <NavaneethKN@di scussions.micro soft.comwrote:
          Peter,
          >
          That was a perfect answer. Thanks for that.
          >
          BTW, will unregistered events won't get collected on GC cycles?
          I don't know what that means. What's an "unregister ed event"? Why
          wouldn't one get collected? All the usual GC rules apply...if the
          instance is reachable, it won't be collected, otherwise it will.

          Pete

          Comment

          Working...