473,503 Members | 1,649 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Clearing Events without -=

Hi,

I have a situation where I need to clear the event sinks from an event
inside a custom class. But I don't know which methods signed up for that
event.

Consider the following example:

public class B
{
public event System.EventHandler DoneIt;

// ....
}

B b = new B();
b.DoneIt += X;

Now eventually suppose I want to "reset" b so that DoneIt == null but I
don't want to completely generate a new object, just the event sinks.
Typically this is done using

b.DoneIt -= X;

But in this case we don't know what X is. B is in a class library and we
have no control or knowedge of what the consumers of that class might do
with DoneIt.

My question is: Is there a way to have b force DoneIt to be null without
explicitly knowing the right hand side of += since it happened outside our
code?

Thanks in advance,
Michael

ps In case you haven't tried this before: b.DoneIt = null; does not compile.
Nov 15 '05 #1
13 13890
Michael Kennedy [UB] <mk******@REMOVETHIS.unitedbinary.com> wrote:
I have a situation where I need to clear the event sinks from an event
inside a custom class. But I don't know which methods signed up for that
event.


If you are not the "owner" of the custom class, you can't do this.
Within the custom class you can clear the event, but if the custom
class doesn't make any means of clearing the event available to you, it
presumably doesn't want you to be able to do so.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #2
Using reflection, you can do b.GetType().GetEvents() or
b.GetType().GetEvent() to find the particular event of interest and use the
EventInfo.RemoveEventHandler() to remove it.

I haven't done this, but a quick look at the docs would lead me to start
here.

Pete

"Michael Kennedy [UB]" <mk******@REMOVETHIS.unitedbinary.com> wrote in
message news:uv**************@tk2msftngp13.phx.gbl...
Hi,

I have a situation where I need to clear the event sinks from an event
inside a custom class. But I don't know which methods signed up for that
event.

Consider the following example:

public class B
{
public event System.EventHandler DoneIt;

// ....
}

B b = new B();
b.DoneIt += X;

Now eventually suppose I want to "reset" b so that DoneIt == null but I
don't want to completely generate a new object, just the event sinks.
Typically this is done using

b.DoneIt -= X;

But in this case we don't know what X is. B is in a class library and we
have no control or knowedge of what the consumers of that class might do
with DoneIt.

My question is: Is there a way to have b force DoneIt to be null without
explicitly knowing the right hand side of += since it happened outside our
code?

Thanks in advance,
Michael

ps In case you haven't tried this before: b.DoneIt = null; does not compile.

Nov 15 '05 #3
"Michael Kennedy [UB]" <mk******@REMOVETHIS.unitedbinary.com> wrote:

<snip>
ps In case you haven't tried this before: b.DoneIt = null; does not compile.


Thats because you used

public event System.EventHandler DoneIt;

"event" protects it from that sort of "abuse". If you change it to

public System.EventHandler DoneIt;

the compilation error will go away - however now you have a publically
accessible field that clients of the object can abuse without the knowledge
of the object - a situation that should be avoided. Simply create a public method
in class B to clear the event sink list, e.g.:

public void ClearDoneIt(){
// Place any Checks here to determine
// it you want to follow the "suggestion"
// to clear DoneIt
DoneIt = null;
} // End method B.RaiseDoneIt

that way you won't have to leave the event sink list so exposed.

Source Code follows:

#define ClearEvent
using System;

namespace ClearEvent {

class TestDriver {
static void Main(string[] args) {

B b = new B();
DoneItSubscriber s1 = new DoneItSubscriber( "First", b );
DoneItSubscriber s2 = new DoneItSubscriber( "Second", b );
Console.WriteLine( "Raising DoneIt Event." );
b.RaiseDoneIt();
Console.WriteLine( "Clearing DoneIt Event sinks." );
#if ClearEvent
b.ClearDoneIt();
#else
b.DoneIt = null;
#endif
Console.WriteLine( "Raising DoneIt Event again." );
b.RaiseDoneIt();
}
}

public class B {

#if ClearEvent
public event System.EventHandler DoneIt;
#else
public System.EventHandler DoneIt;
#endif

public void RaiseDoneIt(){
OnDoneIt( EventArgs.Empty );
} // End method B.RaiseDoneIt

public void ClearDoneIt(){
// Place any Checks here to determine
// it you want to follow the "suggestion"
// to clear DoneIt
DoneIt = null;
} // End method B.RaiseDoneIt

// "Publishing Events Defensively" p.108
// "Programming .NET Components" by Juval Löwry, April 2003 O'Reilly & Associates Inc
// ISBN 0596003471
protected void OnDoneIt( EventArgs e ){
if (null == DoneIt ) return;

Delegate[] delegates = DoneIt.GetInvocationList();
foreach( Delegate del in delegates ){
EventHandler sink = (EventHandler)del;
try {
sink( this, e );

} catch {
Console.WriteLine( "OnDoneIt: Eventhandler raised exception." );
}
}
} // End method B.OnDoneIt

} // end class B

public class DoneItSubscriber {
private string name_;

public DoneItSubscriber( string name, B eventSource ) {
name_ = name;
eventSource.DoneIt += new EventHandler( HandleDoneIt );
}

public void HandleDoneIt( object sender, EventArgs e ){
Console.WriteLine(
name_ + ": handled DoneIt."
);
}
} // end class DoneItSubscriber

}

Nov 15 '05 #4
Hi Pete,

That's an interesting idea. Although working with the typeof(B) alone it
seems like it is not possible to effect instance level events. Maybe it
could effect something with the static events, but I will definitely have a
look.

Thanks!
Michael

"Pete Davis" <pd******@hotmail.com> wrote in message
news:25******************************@news.meganet news.com...
Using reflection, you can do b.GetType().GetEvents() or
b.GetType().GetEvent() to find the particular event of interest and use the EventInfo.RemoveEventHandler() to remove it.

I haven't done this, but a quick look at the docs would lead me to start
here.

Pete

"Michael Kennedy [UB]" <mk******@REMOVETHIS.unitedbinary.com> wrote in
message news:uv**************@tk2msftngp13.phx.gbl...
Hi,

I have a situation where I need to clear the event sinks from an event
inside a custom class. But I don't know which methods signed up for that
event.

Consider the following example:

public class B
{
public event System.EventHandler DoneIt;

// ....
}

B b = new B();
b.DoneIt += X;

Now eventually suppose I want to "reset" b so that DoneIt == null but I
don't want to completely generate a new object, just the event sinks.
Typically this is done using

b.DoneIt -= X;

But in this case we don't know what X is. B is in a class library and we
have no control or knowedge of what the consumers of that class might do
with DoneIt.

My question is: Is there a way to have b force DoneIt to be null without
explicitly knowing the right hand side of += since it happened outside our code?

Thanks in advance,
Michael

ps In case you haven't tried this before: b.DoneIt = null; does not

compile.


Nov 15 '05 #5
Hi,

That is a good idea. I'll see how this idea fits into my architecture. It
looks like it could be a winner.

Thanks!
Michael
"UAError" <nu**@null.null> wrote in message
news:p1********************************@4ax.com...
"Michael Kennedy [UB]" <mk******@REMOVETHIS.unitedbinary.com> wrote:

<snip>
ps In case you haven't tried this before: b.DoneIt = null; does not
compile.
Thats because you used

public event System.EventHandler DoneIt;

"event" protects it from that sort of "abuse". If you change it to

public System.EventHandler DoneIt;

the compilation error will go away - however now you have a publically
accessible field that clients of the object can abuse without the knowledge of the object - a situation that should be avoided. Simply create a public method in class B to clear the event sink list, e.g.:

public void ClearDoneIt(){
// Place any Checks here to determine
// it you want to follow the "suggestion"
// to clear DoneIt
DoneIt = null;
} // End method B.RaiseDoneIt

that way you won't have to leave the event sink list so exposed.

Source Code follows:

#define ClearEvent
using System;

namespace ClearEvent {

class TestDriver {
static void Main(string[] args) {

B b = new B();
DoneItSubscriber s1 = new DoneItSubscriber( "First", b );
DoneItSubscriber s2 = new DoneItSubscriber( "Second", b );
Console.WriteLine( "Raising DoneIt Event." );
b.RaiseDoneIt();
Console.WriteLine( "Clearing DoneIt Event sinks." );
#if ClearEvent
b.ClearDoneIt();
#else
b.DoneIt = null;
#endif
Console.WriteLine( "Raising DoneIt Event again." );
b.RaiseDoneIt();
}
}

public class B {

#if ClearEvent
public event System.EventHandler DoneIt;
#else
public System.EventHandler DoneIt;
#endif

public void RaiseDoneIt(){
OnDoneIt( EventArgs.Empty );
} // End method B.RaiseDoneIt

public void ClearDoneIt(){
// Place any Checks here to determine
// it you want to follow the "suggestion"
// to clear DoneIt
DoneIt = null;
} // End method B.RaiseDoneIt

// "Publishing Events Defensively" p.108
// "Programming .NET Components" by Juval Löwry, April 2003 O'Reilly & Associates Inc // ISBN 0596003471
protected void OnDoneIt( EventArgs e ){
if (null == DoneIt ) return;

Delegate[] delegates = DoneIt.GetInvocationList();
foreach( Delegate del in delegates ){
EventHandler sink = (EventHandler)del;
try {
sink( this, e );

} catch {
Console.WriteLine( "OnDoneIt: Eventhandler raised exception." ); }
}
} // End method B.OnDoneIt

} // end class B

public class DoneItSubscriber {
private string name_;

public DoneItSubscriber( string name, B eventSource ) {
name_ = name;
eventSource.DoneIt += new EventHandler( HandleDoneIt );
}

public void HandleDoneIt( object sender, EventArgs e ){
Console.WriteLine(
name_ + ": handled DoneIt."
);
}
} // end class DoneItSubscriber

}

Nov 15 '05 #6
Hi Jon,

In the situation I outlined, I was the owner of the custom class. But I can
see how if you had a public event and it was "nullable" as I was asking for,
then other classes could mess-up the events by nulling them since it is
public and would be accessable in that way to everyone.

Thanks!
Michael

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Michael Kennedy [UB] <mk******@REMOVETHIS.unitedbinary.com> wrote:
I have a situation where I need to clear the event sinks from an event
inside a custom class. But I don't know which methods signed up for that
event.


If you are not the "owner" of the custom class, you can't do this.
Within the custom class you can clear the event, but if the custom
class doesn't make any means of clearing the event available to you, it
presumably doesn't want you to be able to do so.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 15 '05 #7
Hi Michael,

Thanks for posting. I think the EventInfo.RemoveEventHandler() method can
affect instance level events:

http://msdn.microsoft.com/library/de...us/cpref/html/
frlrfsystemreflectioneventinfoclassremoveeventhand lertopic.asp

As we can see, the first parameter of the method is "object target". It is
the instance that the method operates on to remove the delegate from.

On the other hand, the EventInfo.RemoveEventHandler() method cannot achieve
your goal. The reason is similar to the "-=" operator. For the method to
operate, it needs a second parameter to identify the delegate to remove. If
we have no reference to the delegate, we cannot remove it.

I hope this makes sense.

Regards,

Felix Wang
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Nov 15 '05 #8
Hi Jon,

I think that we can achieve the goal with Reflection, even if we are not
the "owner" of the custom class. The following is a simple C# Console
Application for demonstraton:

using System;
using System.Reflection;

public delegate void MyDelegate();

public class B
{
public event MyDelegate AEvent;
public void RaiseAEvent()
{
if (AEvent != null)
{
AEvent();
} else Console.WriteLine("Event delegate is null");
}
}

public class ClassForMain
{
public static void Main(string[] args)
{
B b = new B();
b.AEvent += new MyDelegate(Hello);
b.RaiseAEvent();

Type t = typeof(B);
FieldInfo f = t.GetField("AEvent", BindingFlags.Instance |
BindingFlags.NonPublic);
f.SetValue(b,null);
b.RaiseAEvent();
}

public static void Hello()
{
Console.WriteLine("Hello");
}
}

Regards,

Felix Wang
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Nov 15 '05 #9
Felix Wang <v-*****@online.microsoft.com> wrote:
I think that we can achieve the goal with Reflection, even if we are not
the "owner" of the custom class. The following is a simple C# Console
Application for demonstraton:


<snip>

Your code is assuming that:

a) You have sufficient access to modify private fields in the relevant
class
b) The event is defined in such a way that there's a field of the same
name

Neither need be true.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #10
Hi Felix,

Yeah, that makes sense. The console app you posted above this message in
this thread is very interesting.

Thank you for the advice,
Michael

"Felix Wang" <v-*****@online.microsoft.com> wrote in message
news:8B**************@cpmsftngxa07.phx.gbl...
Hi Michael,

Thanks for posting. I think the EventInfo.RemoveEventHandler() method can
affect instance level events:

http://msdn.microsoft.com/library/de...us/cpref/html/ frlrfsystemreflectioneventinfoclassremoveeventhand lertopic.asp

As we can see, the first parameter of the method is "object target". It is
the instance that the method operates on to remove the delegate from.

On the other hand, the EventInfo.RemoveEventHandler() method cannot achieve your goal. The reason is similar to the "-=" operator. For the method to
operate, it needs a second parameter to identify the delegate to remove. If we have no reference to the delegate, we cannot remove it.

I hope this makes sense.

Regards,

Felix Wang
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Nov 15 '05 #11
Hi Jon,

Thanks for your reply. I agree with your point (a). However, regarding the
point (b), when we declare a public event in C#, by default, a private
field with type Delegate (MulticastDelegate) will be added by the compiler.
The private delegate field will share the same name as the event normally.

Regards,

Felix Wang
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Nov 15 '05 #12
Felix Wang <v-*****@online.microsoft.com> wrote:
Thanks for your reply. I agree with your point (a). However, regarding the
point (b), when we declare a public event in C#, by default, a private
field with type Delegate (MulticastDelegate) will be added by the compiler.
The private delegate field will share the same name as the event normally.


That's how they're added by default, yes - but it's not how they *have*
to be added. Indeed, many controls *don't* use that mechanism as if you
have a lot of events, only some of which may have any real handlers, it
wastes a lot of memory. You can explicitly specify your own add/remove
parts of the event, in which case the compiler doesn't add any fields
for you automatically.

See section 17.7 of the C# ECMA spec for more details. An example of
not using a single field per event is given in 17.7.2.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #13
Hi Jon,

Thanks for your response. I am aware of the usage of EventHandlerList class
and the optimization. We may also use HashTable to store the delegates. It
is my pleasure to discuss these with you.

Regards,

Felix Wang
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Nov 15 '05 #14

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

Similar topics

0
5020
by: Charles Blaquière | last post by:
While noodling around, looking for a good layout for an "events calendar" page, I came upon a problem that has me stymied. Have a look at http://kpuc.org/events/upcoming-2.html . The basic...
18
8061
by: Niels | last post by:
Hi group, I have some problems with clearing floated divs. My usual method works fine in Konqueror, but not in Firefox. Here's an example: <html><body> <div id='left' style='float:left;...
2
2284
by: Andrey Tarasevich | last post by:
Hello Consider the following HTML code sketch <div> <img src="..." style="float: left"> <p>Paragraph text</p> </div> <hr>
14
12104
by: JPRoot | last post by:
Hi I use the following syntax to have events inherited from base to child classes which works nicely (virtual and override keyword on events). But I am wondering if it is a "supported" way of using...
3
15041
by: Brad | last post by:
I'm working with a DataGrid in C#, and the user needs to be able add and remove columns from the DataGrid on the fly, without opening and closing the form. The scenario is this. I have a setup...
0
1018
by: Lappis | last post by:
I created a handler for evenlog EntryWritten, which works fine until someone clears the log. After clearing the log it won't receice events any longer. Is this a bug or feature? If a feature how to...
2
1300
by: Verdagon | last post by:
Hey everyone. I have this function in my form called "Display", which I call every time the load, resize, and paint events are called. It works fine on paint and resize, but on load it doesnt...
30
3607
by: Burkhard | last post by:
Hi, I am new to C# (with long year experience in C++) and I am a bit confused by the language construct of events. What is it I can do with events that I cannot do with delegates? At the moment...
1
1732
by: ray well | last post by:
i'm loading a combobox from a database in code, by setting the the DataSouce to a table, and the DisplayMember to a field. it loads the first row into the text area of the combobox automatically....
0
7072
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
1
6979
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7449
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
4998
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4666
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3160
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3149
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1498
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
730
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.