Walkthrough: The Unity Event Broker Extension QuickStart

Microsoft Enterprise Library 5.0

DropDown image DropDownHover image Collapse image Expand image CollapseAll image ExpandAll image Copy image CopyHover image

The Event Broker Extension QuickStart demonstrates how you can extend the Unity container by adding a custom extension. The QuickStart implements an event broker for the container as a container extension and demonstrates the new extension using the StopLight application discussed in Walkthrough: The Unity StopLight QuickStart.

The Event Broker Extension QuickStart contains five projects:

  • SimpleEventBroker. This project implements a simple publish and subscribe mechanism that supports multiple event publishers and multiple subscribers.
  • EventBrokerExtension. This project implements the custom container extension that allows applications to publish and subscribe to events using attributes or explicitly using code.
  • StopLight. This project is basically the same as that described in the Unity StopLight QuickStart, but it uses the custom container extension to manage the publishing of, and subscription to, two events within the application.
  • Tests.EventBrokerExtension. A test fixture for the EventBrokerExtension.
  • Tests.SimpleEventBroker. A test fixture for the SimpleEventBroker.

For information about how you can create and use custom container extensions, see Creating and Using Container Extensions.

The following diagram shows the classes and architecture of the Event Broker Extension QuickStart.

If you compare this diagram to the structure of the StopLight QuickStart shown in Walkthrough: The Unity StopLight QuickStart, you can see that the EventBroker Extension QuickStart has the following additional features:

  • The Program class, which registers the type mappings in the container and calls the Resolve method to instantiate the main StopLight form, also adds the SimpleEventBrokerExtension to the container.
  • The SimpleEventBrokerExtension, which inherits from the UnityContainerExtension base class, creates an instance of the EventBroker class that implements the publish and subscribe pattern for distributed events.
  • The EventBroker class creates an instance of the PublishedEvent class that provides the facilities for maintaining a list of event subscriptions and raising events to registered subscribers.
  • The StopLightPresenter, StopLightSchedule, and RealTimeTimer classes include attributes that register event publications and subscriptions with the SimpleEventBrokerExtension class.

The Event Broker Extension QuickStart demonstrates the following features of Unity and the custom container extension mechanism:

Creating a Custom Unity Container Extension

A Unity container extension is a custom class that inherits from the UnityContainerExtension base class and implements extra functionality beyond that available from the container. The extension can access the container and receive notification of registrations taking place within the container. This section describes the significant features of the EventBrokerExtension project.

The class SimpleEventBrokerExtension inherits UnityContainerExtension and creates a new instance of the EventBroker class from the SimpleEventBroker project. It then overrides the Initialize method of the UnityContainerExtension base class.

The code in the Initialize method of the SimpleEventBrokerExtension class, which follows, adds the new EventBroker it creates to the container's Locator so that other classes can locate and reference it easily, and then it adds two strategies to the Unity build pipeline. It adds a reflection strategy to the PreCreation stage that will detect the two attributes that the extension uses (the PublishesAttribute and the SubscribesToAttribute) and a wire-up strategy to the Initialization stage that registers publishers and subscriber delegates with the EventBroker. Finally, it exposes the new EventBroker it created as a property.

C# Copy Code
public class SimpleEventBrokerExtension : UnityContainerExtension,
                                          ISimpleEventBrokerConfiguration
{
  private readonly EventBroker broker = new EventBroker();

  protected override void Initialize()
  {
    
    Context.Container.RegisterInstance(
            broker, new ExternallyControlledLifetimeManager());
    Context.Strategies.AddNew<EventBrokerReflectionStrategy>(UnityBuildStage.PreCreation);
    Context.Strategies.AddNew<EventBrokerWireupStrategy>(UnityBuildStage.Initialization);
  }

  public EventBroker Broker
  {
    get { return broker; }
  }
}
Visual Basic Copy Code
Public Class SimpleEventBrokerExtension
    Inherits UnityContainerExtension
    Implements ISimpleEventBrokerConfiguration

  Private _broker As New EventBroker()

  Protected Overloads Overrides Sub Initialize()
    Context.Container.RegisterInstance( _
            broker, New ExternallyControlledLifetimeManager())
    Context.Strategies.AddNew(Of EventBrokerReflectionStrategy)(UnityBuildStage.PreCreation)
    Context.Strategies.AddNew(Of EventBrokerWireupStrategy)(UnityBuildStage.Initialization)
  End Sub

  Public ReadOnly Property Broker() As EventBroker _
         Implements ISimpleEventBrokerConfiguration.Broker 
    Get
      Return _broker
    End Get
  End Property

End Class

The EventBroker class holds a Dictionary containing entries that map event names to publishers of that event and exposes methods to register publishers and subscribers (named RegisterPublisher and RegisterSubscriber). It also exposes methods to unregister publishers and subscribers and to get a list of publishers or subscribers for a specified event name. Much of the functionality for these methods is in the PublishedEvent class, which stores and exposes lists of all publishers and subscribers.

The wire-up strategy added to Unity by the Initialize method in the previous listing calls the RegisterPublisher and RegisterSubscriber methods of the EventBroker class. This means that, when Unity detects a PublishesAttribute or SubscribesToAttribute in a class that it creates, it automatically registers the class or member as a publisher or a subscriber in the EventBroker.

If the registration is for a publisher, the EventBroker calls the AddPublisher method of the PublishedEvent class. This method adds the new publisher to the list of publishers and wires up an event handler named OnPublisherFiring to the published event. Therefore, when the publisher raises the event, the handler in the PublishedEvent class can iterate through the list of subscriber delegates and invoke each one, as shown in the following code.

C# Copy Code
private void OnPublisherFiring(Object sender, EventArgs e)
{
  foreach(EventHandler subscriber in subscribers)
  {
    subscriber(sender, e);
  }
}
Visual Basic Copy Code
Private Sub OnPublisherFiring(sender As Object, e As EventArgs)
  For Each subscriber As EventHandler in _subscribers
    subscriber.Invoke(sender, e)
  Next
End Sub

Adding an Extension to the Unity Container at Run Time

After you create a custom container extension, you must add it to the Unity container. You can do this by compiling the extension and specifying the type and assembly name in the configuration file for Unity. For details on how to configure Unity container extensions, see Configuring Unity.

However, the EventBroker Extension QuickStart adds the custom SimpleEventBrokerExtension at run time by calling a method of the Unity container class. The StopLight application Program class that initializes the application and loads the main form creates a new UnityContainer instance and registers the concrete types that map to the ILogger and IStoplightTimer classes. It also calls the AddNewExtension method, specifying the SimpleEventBrokerExtension class, as shown in the following code.

C# Copy Code
IUnityContainer container = new UnityContainer()
           .AddNewExtension<SimpleEventBrokerExtension>()
           .RegisterType<ILogger, TraceLogger>()
           .RegisterType<IStoplightTimer, RealTimeTimer>();
Visual Basic Copy Code
Dim container As IUnityContainer = New UnityContainer() _
           .AddNewExtension(Of SimpleEventBrokerExtension)() _
           .RegisterType(Of ILogger, TraceLogger)() _
           .RegisterType(Of IStoplightTimer, RealTimeTimer)()

The container automatically instantiates the extension and calls the Initialize method that you saw in the section Creating a Custom Unity Container Extension of this topic.

Using the Example Event Broker Extension

As shown in the previous diagram, the EventBroker Extension QuickStart uses the custom SimpleEventBrokerExtension container extension to implement the publish and subscribe pattern for two events:

  • The RealTimeTimer class publishes an event named TimerTick that it raises when the timer reaches zero. The StoplightSchedule class subscribes to this event. In the event handler, it updates its index to the lightTimes array (an array of TimeSpan values for the duration of the colors), sets the new duration for the light, and starts the timer running again.
  • The StoplightSchedule class publishes an event named ChangeLight that it raises before it changes the timer duration and restarts the timer. The StoplightPresenter class subscribes to this event. In the event handler, it calls the Next method of the StopLight class to change the color of the light and write a message to the TraceLogger.

To indicate that it publishes the TimerTick event, the RealTimeTimer class uses the Publishes attribute, specifying the name of the event publication, as shown in the following code.

C# Copy Code
[Publishes("TimerTick")]
public event EventHandler Expired;
private void OnTick(Object sender, EventArgs e)
{
  timer.Stop();
  OnExpired(this);
}
Visual Basic Copy Code
<Publishes("TimerTick")> _
Public Event Expired As EventHandler Implements IStoplightTimer.Expired
Private Sub OnTick(ByVal sender As Object, e As EventArgs)
  timer.[Stop]()
  OnExpired(Me)
End Sub

The OnExpired method simply checks that there is an event handler instance and raises the event, as shown here.

C# Copy Code
protected virtual void OnExpired(object sender)
{
  EventHandler handlers = Expired;
  if(handlers != null)
  {
    handlers(this, EventArgs.Empty);
  }
}
Visual Basic Copy Code
Protected Overridable Sub OnExpired(ByVal sender As Object)
  Dim handlers As EventHandler = ExpiredEvent
  If Not handlers Is Nothing Then
    RaiseEvent Expired(Me, EventArgs.Empty)
  End If
End Sub

The StoplightSchedule class subscribes to the TimerTick event by applying the SubscribesTo attribute to a suitable event handler.

C# Copy Code
[SubscribesTo("TimerTick")]
public void OnTimerExpired(Object sender, EventArgs e)
{
  EventHandler handlers = ChangeLight;
  if(handlers != null)
  {
    handlers(this, EventArgs.Empty);
  }
  currentLight = ( currentLight + 1 ) % 3;
  timer.Duration = lightTimes[currentLight];
  timer.Start();
}
Visual Basic Copy Code
<SubscribesTo("TimerTick")> _
Public Sub OnTimerExpired(ByVal sender As Object, ByVal e As EventArgs)
  Dim handlers As EventHandler = ChangeLightEvent
  If Not handlers Is Nothing Then
    RaiseEvent ChangeLight(Me, EventArgs.Empty)
  End If
  currentLight = ( currentLight + 1 ) Mod 3
  _timer.Duration = lightTimes(currentLight)
  _timer.Start()
End Sub

The preceding code shows that the OnTimerExpired event handler raises an event named ChangeLight when it receives the TimerTick event. ChangeLight is the local name of the event, but the StoplightSchedule class also publishes the event using this name, as shown in the following code.

C# Copy Code
[Publishes("ChangeLight")]
public event EventHandler ChangeLight;
Visual Basic Copy Code
<Publishes("ChangeLight")> _
Public Event ChangeLight As EventHandler

Finally, the StoplightPresenter class subscribes the ChangeLight event using an event handler named OnScheduledLightChange. Inside the event handler, it calls the Next method of the StopLight class, as shown in the following code.

C# Copy Code
[SubscribesTo("ChangeLight")]
public void OnScheduledLightChange(Object sender, EventArgs e)
{
  stoplight.Next();
}
Visual Basic Copy Code
<SubscribesTo("ChangeLight")> _
Public Sub OnScheduledLightChange(ByVal sender As Object, ByVal e As EventArgs) _
  _stoplight.Next()
End Sub

The code examples in this section demonstrate how useful the custom SimpleEventBrokerExtension is for working with distributed events and how easy it is to publish and subscribe to events when using Unity to generate instances of the classes used in the application.