[Journal - Parameterizing Event Subscriptions]

Parameterizing Event Subscriptions

Saturday, July 28, 2007

When registering for an event, the subscriber normally uses syntax like this:

someObject.SomeEvent += MyHandler;

The will invoke the Add() method for that event. Suppose you want to enable the subscriber to pass some parameters, for example, controlling the extent of the event subscription, or details about just when or how often to be notified.

One thing you can do is offer regular methods for subscription/unsubscription, and that's fine. However, this may lead to interface bloat - you need two methods for each event, and if you add further twists on controlling event behaviour, you'll end up with a lot of overloading.

Another way is to have the listener implement a callback interface, providing properties that govern subscription details. The listener is available to the sender through the delegate object's Target property. However, this limits this technique to instance methods as event handlers. It also results in having the relevant code shattered all over the place, and makes it more complex in general.

A third solution is to use custom attributes on the handler method:

[EventSubscription(Delayed=true)]
private void HandleIt(object sender, EventArgs e){}

In the Add() method, you can read the delegate object's Method property, then ask for custom attributes. Depending on what data you get, you can do your special thing with regard to raising the event for that listener.

For example, there may be a filter, like "only fire the Changed event for attributes such and such". Or you may fire the event only when the application is idle. Or collapse several notifications into some kine of bulk event.

There are performance considerations (which apply to the event subscription itself only), however: Obtaining the MethodInfo requires reflection - though you might want to read that property anyway, for different reasons. Getting the custom attribute data also takes cycles, but you can cache that information on a per-method basis - given that there are typically more event subscriptions than event handler methods.