Preface

Introduction

EventBroker is a component that you can use to fire and receive notifications in your system.

Features

Loose Coupling:

The subscriber does not have to know the publisher. Both of them only need to know the EventTopic URI (a string uniquely identifying the EventTopic in the system). This facilitates building loosely coupled systems.

Thread Synchronization:

The subscriber defines on which thread the subscription handler is executed:

Same thread as publisher (synchronous)

Background thread (asynchronous)

User interface thread (synchronous or asynchronous)

Publishers can restrict subscriptions to events to be synchronous or asynchronous.

Multiple Publishers/Subscribers:

Several publishers/subscribers can fire/handle the same EventTopic.

Weak References:

Publishers and subscribers are referenced by weak references which will not prevent them from being garbage collected – like in the normal event registration model.

Scope:

Scope per EventBroker:

Only publishers and subscribers that are registered on the same EventBroker are wired together when events are fired. Normally, you'll use a single EventBroker in your system that handles all event notifications. However, in special cases, it is useful to define a new EventBroker for a sub system. This gives you the possibility to define a scope for your event notification.

Scope with hierarchical naming:

Publishers and subscribers can be named in a hierarchical way, and events can be global, to parents only, or to children only. Both publishers and subscribers can define the scope they publish to/receive from.

Background

This EventBroker is based upon the EventBroker from the Composite (UI) Application Block from Microsoft. See the section Comparison to CAB EventBroker below, for differences.

Register the publisher with your event broker (you have to hold an instance of the event broker somewhere in your code). The sample assumes there is a service that holds the event broker instance for us:

The event broker will inspect the subscriber, on registration, for subscription to event topics (methods with the EventSubscription attribute).

If a publisher fires an event topic for that subscribers are registered, then the event broker will relay them to the subscribers by calling the subscription handler methods with the sender and Eventargs the publisher used to fire its event.

Note that if you use the UserInterface handler, then you have to make sure that you register the subscriber on the user interface thread. Otherwise, the EventBroker won't be able to switch to the user interface thread, and will throw an exception.

Execute handler on UI thread asynchronously

The same as above, but the publisher is not blocked until the subscriber has processed the event.

Fire event topics directly on EventBroker

Event topics can be fired directly on the EventBroker without the need of registering a publisher. This comes in handy whenever you need to fire an event topic from an object that lives only very shortly.

A good example for such a scenario is a scheduled job execution. At the scheduled time, an instance of a job class is instantiated and executed. It would be cumbersome to register this instance, fire the event, and unregister it again - it's far easier to fire the event directly on the EventBroker:

eventBroker.Fire("topic", sender, eventArgs);

Scope

Sometimes it is necessary to limit the scope an event is published to. This can be achieved in two different ways:

Multiple instances of event brokers

Subscribers can only listen to events of publishers that are registered on the same event broker. Therefore, an event broker automatically builds a scope.

This is the easiest solution to have several event handling scopes in your application, and should always be preferred. However, sometimes, you need more control over scopes within the objects on one single event broker. This scenario is described in the following section.

Hierarchical naming

Publishers and subscribers can be named by implementing the INamedItem interface. This interface provides a single property:

string EventBrokerItemName { get; }

This allows identifying an object within the event broker whereas the publication and subscription attributes are always bound to the class.

The naming is hierarchical by using the same scheme as namespaces:

Test is a parent of Test.MyPublisher1

Test.MyName1 is a sibling of Test.MyName2

Test.MyName1.Subname is a child of Test.MyName1

Test.MyName1 is a twin of Test.MyName1 (two objects with the same name are twins)

Now, a publisher can define the scope it wants to publish the event to, by defining a scope in the publication attribute:

The first event is a global event that all subscribers can receive. The second event is only passed to subscribers that are parents or twins of the publisher. The third event is only passed to subscribers that are children or twins of the publisher.

A subscriber can define the scope it wants to receive events from accordingly:

The first subscription is a global subscription that will handle all the events passed to it. The second subscription will only be called when a parent of the subscriber is firing the event. The third subscription will only be called when a child of the subscriber is firing the event.

Twins (different objects with the same name) are handled specially. A twin is always a parent and child of its twin, and will therefore will always receive all the events from its twin.

Comparison to CAB EventBroker

As stated in the Background section, my EventBroker is based on the EventBroker from CAB (Composite UI Application Block) from the Practices and Patterns group of Microsoft.

This section describes the differences.

Standalone

The bbv.Common EventBroker can be used standalone. You can use it anywhere in your projects you need notification, without any framework constraints as CAB would require.

Developer guidance

I tried to implement the EventBroker in a way that errors get visible as soon as possible. I will give you some examples of what that means:

If the type of EventHandler the published event provides does not match the signature the subscription handler provides, then an exception is thrown at registration time, instead of when the event is fired.

If you use the UserInterface or UserInterfaceAsync subscription handlers, then an exception is thrown at registration time if no WindowsFormsSynchronizationContext is present, that means the current thread is not the user interface thread. This would lead to cross threading exceptions when handling events.

Subscription handler restrictions

Note: this feature is only available in the version hosted on Sourceforge.net (see the section Download) and not in the attached solution (it's too new ;-) ).

We had the problem that some publisher has to be sure that all subscribers handle its event synchronously. For example, if you publish a cancel event, providing a way for all subscribers to cancel the current operation. Only if no subscriber sets the Cancel property on the CancelEventArgs to true can the publisher proceed with its operation. Therefore, the publisher has to restrict all subscriptions on this event to be synchronous:

If a subscriber registers an asynchronous handler for this event, then an exception is thrown. Note that the exception is thrown at registration time, and not when the event is fired. This simplifies writing consistent code a lot.

Furthermore, a publisher can restrict subscription handlers to be asynchronous because the publisher does not want to be blocked:

Logging

The EventBroker of bbv.Common is quite chatty in terms of log messages. This enables you to see when a publisher fires an event, how they are routed to subscribers, how they are handled, and which exceptions occurred.

Note: bbv.Common uses log4net to log messages. That means, you can configure the level of messages logged for each component.

Extensibility

ThreadOption --> Handler

I replaced the enum ThreadOption with extensible handlers to define the way the event is handled (synchronously, asynchronously).

Scope --> Scope Matcher

You can implement your own scope matchers to provide an event hierarchy that suits your needs instead of specifying a scope with an enum.

Internals

We'll have a look at the internals on a next update of this article. Until then, please refer to the source code available in the download.

Download

The download at the top of this article contains three Visual Studio 2008 projects:

bbv.Common.EventBroker: the event broker component.

bbv.Common.EventBroker.Test: the unit tests (NUnit).

bbv.Common.EventBroker.Sample: a small sample application (basic usage of event broker).

The bbv.Common.EventBroker is part of a larger library containing some other cool components, which can be found here.

This download is just a stripped down version. To try it out, open the solution, set the start up project to bbv.Common.EventBroker.Sample, and hit F5.

Note that the version attached to this article is not the latest available. Be sure to check the Sourceforge page for the latest release.

License

Note that the bbv.Common.EventBroker is licensed under Apache License 2.0, but because the EventBroker contains parts of the CAB from Microsoft, additional license restrictions have to be applied, see file headers in the source code for details.

Comments and Discussions

Thanks very much for creating this excellent class. I downloaded and installed it in a project I'm working on where I need an event aggregator.

Is there a way to use an enum member instead of a literal string when subscribing to and publishing events? That would be much more refactor-friendly in case an event gets renamed, and would allow for intellisense completion of the event topics.

The docs that come with the class seem to suggest being able to use an enum:

Until now, I never used the event broker in an ASP.NET application. It is surely possible, but the problem is that on each request the event broker has to be built and all publishers and subscriber have to be registered. Furthermore, there are hopefully onl a few objects in the state that could reallly benefit. The question is whether this is worth it.

If there are really some loosely coupled components in your application then the event broker can help to simplify notification, if not it is just a performance reducer, so to speak.

Thanks for the replay Urs. we have been looking for a loosely couple event broker and your event broker fit the bill. in our asp.net app each page is made up of very loosely coupled user controls and from time to time these user controls share data and event. i am still not sure how the state management is going to work with the event broker. like you said at each request the event broker has to be built and all publishers and subscribers have to be registered. as this is an asp.net app concurrency of the event broker is something i am still not sure

About concurrency: either you use a different event broker per request (per se thread-safe) or a single event broker and register/unregister publisher and subscribers per request. Both are possible because the event broker is thread-safe itself.

However, I think the first option is much simpler to handle and there is almost no cost to instantiate event brokers.

btw. make sure that you use the latest version from sourceforge (see article)

Please keep me posted on your decision about using event broker. Feedback is very welcome, too.

haha these are exactly what i am trying to do. i think i got the second suggestion working; single event broker, register/unregister publisher and subscribers. we are using microsoft unity to store the event broker as singleton. but i am struggling to get the first suggestion working. the events wouldn't fire; i think its because i re-create the evenbroker. where would you re-instantiate the eventbroker to make sure only one event broker is created per requested?

If you have already a working solution using a single event broker then I see nothing wrong in keeping the register/deregister approach. Just make sure that you unregister the obsolete objects, otherwise (as long as the garbage collector has not collected them) the subscribers will still be called.

When using an event broker per request then you probably would have to instanciate it in the application class on a new request (or something like this; sorry, my last asp.net app was some time ago
Either with Unity as a constant (if this is possible in Unity, I normally use Ninject) or on the request Scope.

I am trying to find a way to unregister/register publisher and subscriber per request. the way its been done we unregister ALL publisher/subscribers whenever a page is been called. that works fine when there is only a single user. things don't work as planned when we have several concurrent users logged on . How would you unregisters "specific" publishers/subcribers" per page reqguest?

I would make sure that the event broker is stored in the session of the user. Then there is no "cross-talk" between different users. Global subscribers and publishers have to be registered on every "user" event broker, of course.

Creating an event broker is very cheap. Registration and deregistration are the operations that can hurt performance. However, I don't have real world experience on the number of registrations/deregistrations you describe you'll have in your application.

There is a potential for performance optimization if necessary (the problem: reflection is used to get events and handler methods. This information could however be cached per type).

You are correct there is a problem but you missed it. This is not "Loosely Coupled Event Handling" as you have advertised.

The point of a loosely coupled event architecture is to provide an abstractions so that Subscriber components do not have any knowledge of potential publishers (Particularly their type!). They also allow a system to function when publishers and subscribers may or may not be present based on security/configuration/etc (Think portal...). Here's a tip: if a type has knowledge of another type at compile time, you are tightly coupled. Coupling is a measure of the direct knowledge and dependency that two types have at COMPILE time. Given that:

1) You have to provide a typename of a class
2) The typename is embedded into the assenbly at COMPILE TIME
3) The typename cannot be changed without recompiling your assembly

You should change the title to the article it is inaccurate and misleading.

The event broker works exactly as you describe it should. Maybe you got confused by the handler type that specifies how the event is handled.

[EventSubscription("topic", typeof(Handler))]

There exist handlers for handling the event on the same thread as the event is fired (Publisher), on a background thread (Background) or in the user interface (UserInterface/UserInterfaceAsync).
This is not the type of the class firing the event!

Therefore, subscriber and publisher only need to know the topic string and the signature of the event. No hard references.

I'm using the event broker in WPF applications without any problems. The synchronization with the dispatcher thread works out of the box.
Therefore, I'd say that it should work with Silverlight, too - but I don't have real evidence.

I'd be happy to hear about your experiences.

About Codeplex: If you can give me some good reasons to switch then I'll do it

I have downloaded your event broker and I was very impressed with it. I am using it a home automation project. I am subscribed to a forum re the hardware I am using in my project and the moderator of the forum asked if I could put my C# source code onto the forum. Since I am using your event broker, am I allowed to post the event broker component (dll) on the forum so that my example can be run?

For short: you can redestribute bbv.Common as long as you pass a notice along, that bbv.Common is licensed under Apache 2.0.

If you change parts of the event broker then you have to be aware that parts of it contain code originally from CAB which is licensed under a special Microsoft license that requests a notice (in code) about this fact.

Therefore, add a notice file, write in there that bbv.Common is licensed under Apache License 2.0 and post it along with your code.

Just a question. I am firing the events directly i.e. eventBroker.Fire(...) rather than using the 'Publisher' way. Is there a disadvantage to directly fire the events? I have one event broker for the whole system.

There is a very small performance disadvantage due to additional object creation. However, this is really minimal.

The main disadvantage is that you introduce a direct coupling to the event broker: the class can then only be used with an event broker. If you use the Publisher way then the class can be used either with an event broker or just the plain old .net way. But, it's up to you to decide, which way suits you better.

We use the direct firing on the event broker only for objects that life very shortly (e.g. scheduled tasks that are created by a scheduler, executed and then disposed) because the register, fire, unregister for a single event would be overkill.