473,387 Members | 1,621 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

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.ProductChanged += new EventHandler(first_ProductChanged);

Product second = new Product("Second product");
second.ProductChanged += new EventHandler(second_ProductChanged);

// 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.

Any help would be great
Oct 21 '08 #1
4 7935
On Mon, 20 Oct 2008 20:37:01 -0700, Navaneeth.K.N
<Na*********@discussions.microsoft.comwrote:
[...]
// 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
Oct 21 '08 #2
On Oct 20, 11:37*pm, Navaneeth.K.N
<Navaneet...@discussions.microsoft.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.
Oct 21 '08 #3
Peter,

That was a perfect answer. Thanks for that.

BTW, will unregistered events won't get collected on GC cycles?
Oct 21 '08 #4
On Tue, 21 Oct 2008 11:18:22 -0700, Navaneeth.K.N
<Na*********@discussions.microsoft.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 "unregistered 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
Oct 21 '08 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: DC Gringo | last post by:
I've got a command button to submit a value from a dropdown list that should then filter a SELECT query. I'm simply appending a WHERE colx = <variableSelectedFromDropdownList>. How do I pass this...
3
by: Beth | last post by:
in the following: this.ExitButton.Click += new System.EventHandler(this.ExitButton_Click); if I saw an equation, such as y +=x; then y = y+x. But what is the meaning in the event handler. I...
0
by: i676373 | last post by:
From: i676...@gmail.com - view profile Date: Fri, Feb 24 2006 2:50 pm Email: i676...@gmail.com Groups: microsoft.public.dotnet.languages.csharp Not yet rated Rating: show options Reply...
0
by: jeyaganapathi | last post by:
I have created a Datagrid at runtime with ItemTemplate. I need to add a event handler "ItemDataBound" for that Datagrid object. How to do that? Any one pls help me... Thanks in Advance.... ...
4
by: eggie5 | last post by:
I have this even handler (using prototype.js): showCommentsLinks.observe('click', function(event) { alert('hi') }); It's attaching to a link element: <a id="showCommentsLink"...
5
by: zlf | last post by:
I have an UserControl created by other component, its creator attachs some event handlers to MouseDoubleClick event, but I do not like those events to be triggered while it is db-clicked. I want to...
3
by: wolverine | last post by:
Hi, I am injecting a javascript code into html pages and attaching some dom events to some elements via attachEvent (IE only). I just want to know that is there any chance by which my event...
1
by: cradius | last post by:
I've got a custom user control, with a DataList, that is dynamically added to the page. In the DataList is an ImageButton that, when clicked, fires off the ItemCommand event of the DataList and...
2
by: wolverine | last post by:
Hi All, In Mozilla Firefox, to onblur and onfocus event of each and every html element, the browser itself will attach a native event handler. I mean if you type,...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.