Leveraging the EventHandler Delegate More Effectively

If you are now coding in .Net 2.0/3.0/3.5 and are creating types that expose events. Chances are you have started leveraging the EventHandler delegate that frees you from creating custom delegate signatures for events anymore. If not this post is for you. Let’s say that you want to expose an event that another object could consume. Normally you would follow these steps:

  1. Create a type that inherits from EventArgs if the event is going to propagate event specific data. This step is optional as you may not have any custom data to propagate.
  2. Create a delegate signature for the event. If you are not using a custom EventArgs derivative, then you can get away with just leveraging the EventHandler delegate that already exists in the framework.
  3. Create the type that is going to raise the event and have it declare the event using either implicit or explicit event registration.
  4. Create a method on the type that will raise the event.

In .Net 2.0/3.0/3.5 these steps can now become:

  1. Create a type that inherits from EventArgs if the event is going to propagate event specific data. This step is optional as you may not have any custom data to propagate.
  2. Create the type that is going to raise the event and have it declare the event using either the EventHandler delegate type for an event that does not propagate custom data, or leverage the generic EventHandler delegate to declare an event bound to the specific EventArgs derivative you need to use. Again you can use either implicit or explicit event registration.
  3. Create a method on the type that will raise the event.

This can actually become slightly better. Instead of always creating a class that derives from EventArgs if you need to pass custom data; create a parameter object that encapsulates the information you would want to propagate in the event. This class does not need to inherit from EventArgs. Then create the following utility class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class EventArgs<T> : EventArgs
{
    private T eventData;


    public EventArgs(T eventData)
    {
        this.eventData = eventData;
    }


    public T EventData
    {
        get { return eventData; }
    }
}

This means that the 3 steps above can now be changed to:

  1. Create a parameter object that encapsulates any information you want to propagate in the event.. This step is optional as you may not have any custom data to propagate.
  2. Create the type that is going to raise the event and have it declare the event using either the EventHandler delegate type for an event that does not propagate custom data, or leverage the generic EventHandler delegate, with the generic EventArgs class to declare an event bound to the specific parameter object you need to use. Again you can use either implicit or explicit event registration.
  3. Create a method on the type that will raise the event.

So if I had a parameter object that looked like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ReportingPeriod
{
    private DateTime start;
    private DateTime end;


    public DateTime Start
    {
        get { return start; }
    }

    public ReportingPeriod(DateTime start, DateTime end)
    {
        this.start = start;
        this.end = end;
    }
}

I would be able to create a type that raises an event to propagate this data as follows (using implicit registration):

1
2
3
4
public class ReportTrigger
{
    public event EventHandler<EventArgs<ReportingPeriod>> RunReport;
}

Or using explicit registration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ReportTrigger
{
    private EventHandler<EventArgs<ReportingPeriod>> subscribers;

    public event EventHandler<EventArgs<ReportingPeriod>> RunReport
    {
        add
        {
            subscribers += value;
        }
        remove
        {
            subscribers -= value;
        }
    }
}

Develop With Passion!

Comments