Using EventsObject

SharpObservation exposes two base classes - EventsObject and DisposableEventsObject - which provide management of an EventHandlerList so that the declaration of the events do not increase the memory footprint of instances. The .NET EventHandler list is targetted at Component development, and isn't as well optimized as it could be for general use. SharpObservation re-implementats EventHandlerList to give the best possible combination of tiny memory footprint for classes with many events, whilst offering good performance when events are fired.

To declare an event:
public class ExampleClass  : EventsObject
{
    protected readonly static EventKey<AccountCreditedEventHandler> AccountCreditedEventKey = new EventKey<AccountCreditedEventHandler>();

    public event AccountCreditedEventHandler AccountCredited
    {
        add { AddHandler( AccountCreditedEventKey, value); }
        remove { RemoveHandler( AccountCreditedEventKey, value); }
    }
}

To fire it:
protected virtual void AccountCredited(decimal creditAmount)
{
    RaiseEvent( AccountCreditedEventKey, c => c( this, new AccountCreditedEventArgs( creditAmount )));
}

EventsObject overloads the method RaiseEvent, which always hasat least the following two arguments:
  1. Key - used to distinguish the event from others, which can be any arbitrary object.
  2. Callback - A callback, which is invoked if any delegates are attached to the event.

In the example above, two objects get created before any attached delegates are invoked:
  1. A new AccountCreditedEventArgs, which is passed to the delegates.
  2. An instance of the anonymous method (c =>), which is required in order for the callback to pass creditAmount to the constructor of AccountCreditedEventArgs.

To further improve performance, RaiseEvent offers overloads that simplify passing additional arguments to the Callback, such that the following code is possible:
protected virtual void AccountCredited(decimal creditAmount)
{
    RaiseEvent( AccountCreditedEventKey, creditAmount, ( invoke , amt ) => invoke( this, new AccountCreditedEventArgs( amt )));
}
In the snippet above, the second argument (creditAmount) is passed as the second argument to the callback (amt). Invoking RaiseEvent in this manner allows the compiler to implement the lambda as a static method instead of as an anonymous type, which in turn improves performance... because now only the AccountCreditEventArgs needs to be instantiated.

Last edited Oct 28, 2010 at 8:29 PM by maranite, version 4

Comments

No comments yet.