Hi Peter,
your reply was perfect for a situation where the Subscribed class is only
called from one subscriber.
In my particular situation I have a class A which has few events defined,
Class B, class C ... calls same instance of class A and adds an event handler
individually. I have not control over either Class A or B, C...
I need to clear all the event handlers for the instance of the class A.
Thanks for your support in advance
Kasim Husaini
"Peter Duniho" wrote:
> On Mon, 20 Oct 2008 20:37:01 -0700, Navaneeth.K.N
> <(E-Mail Removed)> wrote:
>
> > [...]
> > // need to clear the ProductChanged event handlers here
> > // I can't get the invocation list of "Product.ProductChanged" 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<> instance can be used for that.
>
> For example (error-checking removed for clarity, uncompiled code):
>
> class MyClass
> {
> private Dictionary<Product, EventHandler> _dictEventForwarder =
> new Dictionary<Product, EventHandler>();
>
> private void _Subscribe(Product product, EventHandler handler)
> {
> EventHandler handlerOld;
>
> if (_dictEventForwarder.TryGetValue(product, out handlerOld))
> {
> handlerOld += handler;
> }
> else
> {
> handlerOld = handler;
> product.ProductChanged += _ForwardingHandler;
> }
>
> _dictEventForwarder[product] = handlerOld;
> }
>
> private void _Unsubscribe(Product product, EventHandler handler)
> {
> EventHandler handlerNew = _dictEventHandler[product] - handler;
>
> if (handlerNew == null)
> {
> _dictEventHandler.Remove(product);
> product.ProductChanged -= _ForwardingHandler;
> }
> else
> {
> _dictEventHandler[product] = handlerNew;
> }
> }
>
> private void _Clear(Product product)
> {
> _dictEventHandler.Remove(product);
> product.ProductChanged -= _ForwardingHandler;
> }
>
> private void _ForwardingHandler(object sender, EventArgs e)
> {
> _dictEventForwarder[(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
>
|