Fork me on GitHub

Event Broker

Motivation

Using .net events throughout the application brings along some problems. For example if you have an event that can be fired by several sources, interested instances need to know every single source and need to register the event directly on them. Doing so, the classes in the application become tangled. This raises problems when you need to change the routing of events because you have to change the code in a lot of places.

Furthermore, in plug-in architectures, the plug-in should not access classes internal to the core directly. Therefore it's difficult to integrate them into the notification infrastructure.

Finally, .net events are handled always on the same thread as the one the event was fired. When listening for example to an event fired by a worker thread on a UI component, the UI component always has to check whether thread switching to the user interface thread is needed and if so switch the thread before manipulating the user interface elements. Otherwise, a cross-thread exception will occur (in debug mode) or you put your application at risk of failure (in release mode).

The event broker of Appccelerate solves these problems for you.

Features

For a quick introduction see the Tutorial.
For the specification see Specification

EventBroker

EventBroker overview

The EventBroker takes the role of a mediator between publishers - instances firing events - and subscribers - instances listening to events. This decouples publisher and subscribers because they only need to know the event broker and the event topic they are interested in.

This also gives you the possibility to define multiple publishers and/or subscribers for a single event topic. Therfore, it is very easy to add or remove additional publishers or subscribers wihtout the need to change any existing code.

Automatic thread switching can easily be used by simply specifing on the subscriber how the event should be handled: on the same thread as the publisher fired the event, on a background thread or on the user interface thread.

Registration of Publishers and Subscribers by Attribute

The normal way how publishers and subscribers mark the events or event handler methods so that the event broker recognizes them is by attributes. You simply mark an event with the [EventPublication] attribute. Likewise, a handler method is marked with [EventSubscription].

Registration of Publishers and Subscribers over an interface

If you have multiple implementations of an interface (for example a plug-in), you can define on the interface itself, which events or event handler methods should by used. This allows you to define the interaction with the event broker once on the interface for all implementations.

Registration of Publishers and Subscribers by Event Broker Registrar

Due to the fact that values used by an attribute have to be compile time constant, you can fallback to the registration by the event broker registrar in more advanced cases. This gives you full flexibility how you register events and event handler methods on the event broker. You can even register events and handler methods of external classes, without having to write any decoration code.

Simplified Handler Methods

When you are not interested in the sender argument, or want to directly access the value of a EventArgs<T> then simplified handler methods are for you.

Direct Event Broker Interaction

In cases where it does not make sense to register an instance on the event broker, you can directly fire events onto the event broker without a publisher. This is for example very useful with scheduled tasks. These tasks are created to perform some task and are then garbage collected. Therefore it would be overkill to register the tasks as a publisher, fire the event and then unregister the task and collect it.

Event Broker Handlers

Handlers a responsible for executing a handler method of a subscriber. There are built-in handlers for executing on the same thread as the event was fired, on a background thread, on the user interface thread synchronously and on the user interface thread asynchronously.

You can provide your own handler to control execution in additional ways.

Matchers

Matchers can be used to take control of the routing of events. A matcher can prevent that an event is passed to a certain subscriber. An example of this is, that an event that can be canceled is passed to further subscribers when it is already canceled. Or an event should only be passed to a subscriber matching a certain criteria.

Exception Handling

The publisher of an event most likely does not know what to do with an exception thrown by a subscriber. This is a result of the decoupling. Therefore, the event broker gives you the possibility to take control of the exception handling by using extensions.

Extensions

You can use extensions to add functionality to the event broker. Examples are the DistributedEventBroker (sending events over process boundaries) and MappingEventBroker (mapping event arguments to other types) extensions. Extensions can also be used to implement logging or take control of exception handling.

Logging

Logging is implemented with an extension. In the SourceTemplates package there is a sample logger for log4net. You can easy write your own logging mechanism by writing an extension.

Testability

Testing multi-threaded, loosly coupled systems is a big challange. Therefore the event broker supports you by providing infrastructure to make execution of events always synchronous. There is no need for using signals or locks in your unit tests.