Events and delegates
Messages   Related Types
This message was discovered on microsoft.public.dotnet.languages.csharp.
Responses highlighted in red are from those people who are likely to be able to contribute good, authoratitive information to this discussion. They include Microsoft employees, MVP's and others who IMHO contribute well to these kinds of discussions.
Post a new message to this list...

Sgt. Sausage
NOTE: I'm new to c#, but not to programming.

For reasons unimportant to the discussion below, I need to be able
to dynamically, at run time, discover the set of all objects listening to
another object's events.

Given some jRandomType, I've figured out how to get the Events
themselves via reflection and GetEvents/EventInfo. This will give me
a list of the Events that jRandomType wants to raise -- but that's only
half the battle.

Now, the part that's got me stumped: Once I have a list of Events
that a Type raises, how do I get from there to iterating through the
subscribers that are listening to the Events on some instance of
jRandomType?

I understand that the Events are defined by the *class*, and the
listeners are registered on a particular *instance* of that class -- e.g.
a given class may raise a single Event, but three instances of that
class may have three different listeners registered. That's not a big
conceptual problem for me. But -- given that I can find the Events
raised via reflection, how do I find out what's subscribed as a
listener on a particular instance?

Is this a case of "you can't get there from here" ? Or, is there an
easy way I'm not finding in the docs?

Thanks for your help.

Reply to this message...
 
    
Jon Skeet [C# MVP] (VIP)
Sgt. Sausage <Click here to reveal e-mail address> wrote:
[Original message clipped]

You can't in all cases. In some cases it's relatively straightforward.
If the event has been defined in C# as:

public event Foo;

then the compiler will have generated a field (also called "Foo" with
the MS compiler, but it's not guaranteed) of the appropriate delegate
type.

There's no guarantee that it's been done that way. For instance, you
could write a perverse event:

public event Amnesiac
{
add {}
remove {}
}

which basically doesn't act properly at all - it forgets whatever is
added to it!

--
Jon Skeet - <Click here to reveal e-mail address>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Reply to this message...
 
    
mdb
Jon Skeet [C# MVP] <Click here to reveal e-mail address> wrote in
news:Click here to reveal e-mail address:

[Original message clipped]

Assuming that the event is formed in a normal manner, though, you can
access the Method and Target parameters of the event delegates...

public event Event_Handler evt;
Delegate[] delArray = evt.GetInvocationList();
for(int i=0; i<delArray.Length; i++)
{
    Delegate ev = delArray[i];
    Trace.WriteLine(ev.Method);
    Trace.WriteLine(ev.Target);
}

-mdb
Reply to this message...
 
    
Sgt. Sausage
"mdb" <m_b_r_a_y@c_t_i_u_s_a__d0t__com> wrote in message
news:Xns95638D9FB17DBmbrayctiusacom@207.46.248.16...
[Original message clipped]

Thanks, but that doesn't get it either.

Given evt.GetInvocationList() -- how does one do this
dynamically, at runtime. You knew, at compile time, that
it's "evt". I don't know this.

I know there's an event named "evt" -- I got that via the
Reflection mentioned in my original post. How do I,
at run time, do something like:

this.("evt").GetInvocationList

or, more to my question:

EventInfo[] events = this.GetType().GetEvents( BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic );

for (int i = 0; i < events.Length; i++)
{

// This is the line (below)

this.(events[i].Name).GetInvocationList //wrong!!

// how do I get the InvocationList, knowing that I've got the name
// of the event in events[i].Name ???

}

Reply to this message...
 
    
Sgt. Sausage
"Sgt. Sausage" <Click here to reveal e-mail address> wrote in message
news:3vl1d.19890$Click here to reveal e-mail address...
[Original message clipped]

Hate to reply to my own post, but on another forum I found this in the
archives:

Recently I wanted to test whether we were successfully releasing
all our event subscriptions when an object was disposed. I thought
this would be a simple task, use Type.GetEvents() to get the events
and then use the resulting EventInfo's to get a list of subscribers. Not
quite so simple, while EventInfo has methods to add and remove events
, it has no invocation list. After a bit more work I discovered the
trick
is to ask for the events as fields and then cast the resulting object to
Delegate. Now I can invoke GetInvocationList(). Too bad MS didn't
include GetInvocationList() on the EventInfo. Problem solved: our unit
tests are starting to get vey good at catching subscriber leaks.

The thread is old, and long since dead.

If anyone knows the actual code to do as described above, I'd
like to see it.

Thanks.

Reply to this message...
 
    
Sgt. Sausage
"Sgt. Sausage" <Click here to reveal e-mail address> wrote in message news:TGl1d.19891
[Original message clipped]

Again with the replying to my own post -- figured it out.

Reply to this message...
 
    
Sgt. Sausage
"Jon Skeet [C# MVP]" <Click here to reveal e-mail address> wrote in message
news:Click here to reveal e-mail address...
> Sgt. Sausage <Click here to reveal e-mail address> wrote:

[snip]

[Original message clipped]

That's not really any help now is it? <grin>

[snip]

So, in this case, how do I grab it and iterate through the listeners?

Reply to this message...
 
 
System.Diagnostics.Trace
System.Reflection.BindingFlags
System.Reflection.EventInfo
System.Type




Ad
MBR BootFX
Best-of-breed application framework for .NET projects, developed by Matthew Baxter-Reynolds and MBR IT
 
 Copyright © Matthew Baxter-Reynolds 2001-2008. '.NET 247 Software Development Services' is a trading style of MBR IT Solutions Ltd.
Contact Us - Terms of Use - Privacy Policy - www.dotnet247.com