tags:

views:

2755

answers:

6

Is there a way to tell if an event handler has been added to an object? I'm serializing a list of objects into/out of session state so we can use SQL based session state... When an object in the list has a property changed it needs to be flagged, which the event handler took care of properly before. However now when the objects are deserialized it isn't getting the event handler.

In an fit of mild annoyance, I just added the event handler to the Get property that accesses the object. It's getting called now which is great, except that it's getting called like 5 times so I think the handler just keeps getting added every time the object is accessed.

It's really safe enough to just ignore, but I'd rather make it that much cleaner by checking to see if the handler has already been added so I only do so once.

Is that possible?

EDIT: I don't necessarily have full control of what event handlers are added, so just checking for null isn't good enough.

+2  A: 

If this is the only handler, you can check to see if the event is null, if it isn't, the handler has been added.

I think you can safely call -= on the event with your handler even if it's not added (if not, you could catch it) -- to make sure it isn't in there before adding.

Lou Franco
+1  A: 

EventHandler.GetInvocationList().Length > 0

benPearce
doesn't this throw when the list == null?
borisCallens
+15  A: 

From outside the defining class, as @Telos mentions, you can only use EventHandler on the left-hand side of a += or a -=. So, if you have the ability to modify the defining class, you could provide a method to perform the check by checking if the event handler is null - if so, then no event handler has been added. If not, then maybe and you can loop through the values in Delegate.GetInvocationList. If one is equal to the delegate that you want to add as event handler, then you know it's there.

public bool IsEventHandlerRegistered(Delegate prospectiveHandler)
{   
 if ( this.EventHandler != null )
 {
  foreach ( Delegate existingHandler in this.EventHandler.GetInvocationList() )
  {
   if ( existingHandler == prospectiveHandler )
   {
    return true;
   }
  }
 }
 return false;
}

And this could easily be modified to become "add the handler if it's not there". If you don't have access to the innards of the class that's exposing the event, you may need to explore -= and +=, as suggested by @Lou Franco.

However, you may be better off reexamining the way you're commissioning and decommissioning these objects, to see if you can't find a way to track this information yourself.

Blair Conrad
This doesn't compile, EventHandler can only be on the left hand side of += or -=.
Telos
Ah yes. Good point. Incorporated.
Blair Conrad
Removed down vote upon further explanation. SQL state is pretty much destroying the entire idea here... :(
Telos
Thanks Blair and SO search, just what I was looking for (annoying you can't do it outside the class though)
George Mauer
A: 

Yeah just compare to null

if(event != null) 
{ 
  // yup you've got handlers registered... :) 
}
stephbu
+2  A: 

This example shows how to use the method GetInvocationList() to retrieve delegates to all the handlers that have been added. If you are looking to see if a specific handler (function) has been added then you can use array.

public class MyClass
{
  event Action MyEvent;
}

...

MyClass myClass = new MyClass();
myClass.MyEvent += SomeFunction;

...

Action[] handlers = myClass.MyEvent.GetInvocationList(); //this will be an array of 1 in this example

Console.WriteLine(handlers[0].Method.Name);//prints the name of the method

You can examine various properties on the Method property of the delegate to see if a specific function has been added.

If you are looking to see if there is just one attached, you can just test for null.

Jason Jackson
GetInvocationList() is not a member of my class. In fact, I can't seem to find this method on any object or handler I have access to...
Telos
I fixed the code. It is a member of the Event in question.
Jason Jackson
I had tried that too, apparently you can only access the event like that from inside the class. I'm doing this generically, and as others have mentioned event handlers are probably getting lost anyway. Thanks for the clarification!
Telos
+1  A: 

If I understand your problem correctly you may have bigger issues. You said that other objects may subscribe to these events. When the object is serialized and deserialized the other objects (the ones that you don't have control of) will lose their event handlers.

If you're not worried about that then keeping a reference to your event handler should be good enough. If you are worried about the side-effects of other objects losing their event handlers, then you may want to rethink your caching strategy.

CodeChef
D'oh! Hadn't even thought of that... though it should have been obvious considering my original problem was my own handler getting lost.
Telos