| Home | Biography | Speaking | Articles | Books | Music |
One idea I’ve had lately for Spackle.NET is to add a class called ScopedEventHandler. The motivation for this class comes from this code:
var provider = new EventProvider();
var handler = new EventHandler((sender, e) =>
Console.Out.WriteLine("Caught broadcast via manual."));
provider.Broadcast += handler;
try
{
provider.Speak();
}
finally
{
provider.Broadcast -= handler;
}
If you don’t do the “-=” thing, you can leak memory. You could use WeakReference, but let’s stick with the traditional approach but have a disposable object do that for us:
var provider = new EventProvider();
var handler = new EventHandler((sender, e) =>
Console.Out.WriteLine("Caught broadcast via scoped."));
using(var scope = new ScopedEventHandler(provider, "Broadcast", handler))
{
provider.Speak();
}
Now, you may be wondering why I’m passing in a string here, rather than the actual event. Let’s take a look at EventProvider:
public class EventProvider
{
public event EventHandler Broadcast;
public void Speak()
{
if(this.Broadcast != null)
{
this.Broadcast(this, new EventArgs());
}
}
}
What I wanted to do was this:
using(var scope = new ScopedEventHandler(provider.Broadcast, handler))
Where the implementation of the constructor looked like this:
public ScopedEventHandler(EventHandler provider, EventHandler listener)
{
provider += listener;
}
But that lead to this compilation error:
Error 1 The event 'Playground.EventProvider.Broadcast' can only appear on the left hand side of += or -= (except when used from within the type 'Playground.EventProvider').
This is compiler error CS0070.
So I’m stuck with Reflection:
public ScopedEventHandler(object provider, string eventName, Delegate listener)
{
var eventInfo = provider.GetType().GetEvent(eventName);
eventInfo.AddEventHandler(provider, listener);
}
The end result is the client code is clearer and easier in my mind, but the API seems kind of dorky. However, I don’t see another way around this. Any suggestions?
Published: 12.02.2008 11:23:50 AM CST