Event Broker – Introduction

Some of you might already be familiar with the bbv.Common.EventBroker. For those who aren’t I want to give a quick overview of the bbv.Common.EventBroker because knowledge about the event broker is crucial for my future posts about the distributed event broker.

The event broker acts as a mediator between a publisher of notifications (aka publisher) and a consumer of notifications (aka subscriber). The event broker transparently integrates into the usage of classic .NET events by applying a set of attributes either to the publisher’s event or the subscribers event handler. The publisher and the subscriber don’t need to know each other during design time, they are wired up during run time.

In comparison to classical .NET events the bbv.Common.EventBroker offers the following advantages:

  • Synchronous and asynchronous notification
  • Automatic thread switching: to background or UI thread
  • Loose coupling of event topic publishers and subscribers
  • Publishers and subscribers are referenced by weak references. Therefore they can be garbage collected
  • Multiple publishers and/or subscribers for a single event topic
  • Matchers for publications and subscriptions
  • Thorough customizable logging
  • Extension support

Let’s look into an example…

A publisher of an event could look like:

public class PublisherComponent {
	[EventPublication("topic://SomethingInteresting")]
	public event EventHandler SomethingInteresting;

	protected void OnSomethingInteresting() {
		var handler = this.SomethingInteresting;
		if(handler != null) {
			handler(this, EventArgs.Empty);
		}
	}
}

How the subscriber can subscribe to events:

public class SubscriberComponent {
	[EventSubscription("topic://SomethingInteresting", typeof(Publisher))]
	public void HandleSomethingInteresting(object sender, EventArgs e) {
		// Do something here
	}
}

All we have to do is register both publisher and subscriber on the event broker.

EventBroker eb = new EventBroker();
PublisherComponent p = new PublisherComponent();
eb.Register(p);
SubscriberComponent s = new SubscriberComponent();
eb.Register(s);

When both components are wired up the publisher can fire its events like normal .NET events. The event broker dispatches the event to all interested subscribers registered on the same event broker instance. Imagine how powerful this becomes when you are using a container like ninject, windsor, structuremap… You’ll have the power to auto hook up instances on one or multiple event brokers.

Its true power comes into play when you are leveraging the multithreading and thread synchronization capabilities of the event broker. This can be done by specifying handler types on the subscription and eventually handler restrictions on the publication. A subscriber can specify whether its events are handled synchronously or asynchronously. A publisher can constrain how its event can be handled (synchronously or asynchronously). This is needed for example in events with results in the event arguments that are evaluated by the publisher after firing the event (-> constraint for synchronous handling). A subscriber can request an automatic thread switch if needed onto a background thread or the user interface thread – thus eliminating the need for manual thread switching (no need for Control.Invoke anymore). There exist following options:

  • handle on current thread (use Publisher handler)
  • handle on background thread from ThreadPool (use Background handler)
  • handle synchronously on user interface thread (use UserInterface handler)
  • handle asynchronously on user interface thread (use UserInterfaceAsync handler)

More details about the event broker can be found here. For details regarding performance see Urs’ post: https://www.planetgeek.ch/2009/07/12/event-broker-performance/

About the author

Daniel Marbach

15 comments

  • How would you do “Find usages” of certain event? How do I know easily where given event is used/handled/published? Don’t say “search”, it happens that I do taiping erors very often…

    I’m looking at Event Aggregator pattern implementation and I can see how I can refactor everything by having strongly typed payload. Is your approach similarly refactor-able?

    Is it a good practice to have event topics as consts?
    (I have done it with CAB/Prism still don’t like it)

  • Hy Richard,
    As I understand (but I’m not really familiar with Rx) is that Rx uses observable sequences and LINQ-style query operators. The data is passed as asynchronous data streams with observables. This means that the subscriber is strong referencing the holder (publisher) of the data stream. I see Rx advantages more in filtering of events where you know the publisher and the event brokers strength more in loose coupling of publishers and subscribers. Does that make sense?

  • Hy Valeriu,
    I must admit that is the major drawback of the event broker implementation. Although strings offer more advanced scenarios (for example you can subscribe to an event topic and handle it with an event argument which is higher up in the inheritance tree) it is certainly a bit more error prone than strongly typed payloads.

    We use in all our projects constants for topics which allows to refactor and rename events in centralized places. By convention we name the class [NameOfTheEventBroker]Topics. For example if you have only one event broker in your application (let us name it global event broker) we would call it GlobalEventBrokerTopics.

    Hope that helps

  • @Valeriu Caraulean
    Another drawback of this approach is that in case of event arguments that cannot ba matched, you get a runtime error instead of a compile error.

    But that is the prize to pay for complete decoupling with its benefits of better changeability, extensibility, testability, refactorability, simpler build-up and structuring.

  • Can I use the bbv Event Broker without enabling the logging (log4net)? If yes, how do I do that? If I want to handle all the events on a background thread (instead of on publisher thread) would that affect the application performance? Also just curious, what does ‘bbv’ stand for?

    – Thanks

  • Hy bob,
    Yes you can. The logging part is provided as an extension if you are using the latest version that you can find on nuget. By default the event broker comes without logging enable. The background handler uses the default thread pool. You are restricted to the available threads the default thread pool can provide you. bbv stands for bbv Software Services Ag. bbv invests time and money into the bbv.Common framework to keep it alive and maintained. bbv sees great value in open source projects.

  • No problem. Be sure to checkout also the new bootstrapper, the evaluation engine, the state machine, the distributed event broker… Let us know if you have any questions!

  • Hi Daniel, here I am back with more questions. I have two assemblies with numerous classes in them. They act as publishers in one way and also as subscribers (for a different set of events). There going to be hundreds of these events. Do I have to go through the pain of registering each one of these objects with the broker? Or is there a way the broker can resolve all the event topics, and their publishers and subscribers in a given assembly?

    Thanks

  • Hy Bob,
    No usually not. Do you have a dependency injection container in place? For example in ninject there are OnActivation and OnDeactivation hooks. We use that to automatically register new instances on the event broker and deregister when the instance goes out of scope. Normally objects should never concern itself with registering on the event broker. This should be handled by an external component such as the DI container.
    Daniel

By Daniel Marbach

Recent Posts