Loosely coupled application wide events I have a much needed rewrite of an inherited application ahead of me and have started to sketch out some possible solutions / build some prototypes for different parts of the application.

I'd like to have some feedback if this is a good approach to provide application events.

Goals:


Loosely coupled
Strictly typed / refactor friendly
Declarative
Adhere to SRP (Single responsibility principle)
Lightweight


All events are classes derived from EventBase. An IoC Container will handle lifetimes of brokers and subscribers. Constructor injection is used. All types implementing IEventSubscriber&lt;&gt; (where T : EventBase) will be automatically registered in the container. My DefaultEventBroker implementation then has an optional IEnumerable&lt;IEventSubscriber&lt;&gt;&gt; dependency, which the container will resolve to all visible subscribers for a given event type. Under the hood a System.Reactive.Subjects.Subject&lt;&gt; (Microsoft Reactive Extensions) will do the heavy lifting.

Essentially I provide two ways to subscribe to events:

Subscribe by setting a dependency on (one or more) IEventBroker&lt;>

public class MyEventListeningComponent
{
    public MyEventListeningComponent(IEventBroker&lt;ProgramStartedEvent&gt; eventBroker)
    {
        eventBroker.Subscribe(e =&gt;
        {
            Console.WriteLine("[MyEventListeningComponent] Program Started: {0}", e.StartDate.ToString());
        });
    }
}


Subscribe by implementing (one or more) IEventSubscriber&lt;>

public class MyEventSubscriber : IEventSubscriber&lt;ProgramStartedEvent&gt;, IEventSubscriber&lt;ProgramEndedEvent&gt;
{
    public void OnNext(ProgramStartedEvent value)
    {
        Console.WriteLine("[MyEventSubscriber] OnNext: Program Started: {0}", value.StartDate.ToString());
    }

    public void OnNext(ProgramEndedEvent value)
    {
        Console.WriteLine("[MyEventSubscriber] OnNext: Program Ended: {0}", value.EndDate.ToString());
    }
}


Any more or less obvious pitfalls? Suggestions?

Side note: IEventSubscriber&lt;&gt; is essentially an IObserver&lt;&gt; without the OnCompleted and OnError methods, because I can subscribe to multiple event types by implementing IEventSubscriber&lt;&gt; with different generic type arguments and I wouldn't be able to get an event type context in OnCompleted and OnError (because those methods do not have generic type arguments). I'm relatively sure I won't be needing those hooks in this scenario anyway.

Edit: Events are raised (or published) via IEventBroker&lt;&gt;

public class MyEventRaisingComponent
{
    public MyEventRaisingComponent(IEventBroker&lt;ProgramStartedEvent&gt; eventBroker)
    {
        eventBroker.Publish(new ProgramStartedEvent() { StartDate = DateTime.Now });
    }
}
The code itself looks good, but I would look into providing a single way of subscribing to events, it will make the job easier for other developers reading and changing the code.

The first method of subscribing (via IEventBroker&lt;T&gt; injection) requires subscriber object to be created first, so it may not receive all events that you may expect it to receive. Every time you create an instance of subscriber it adds a new event subscription thus causing potential memory leaks and side effects. You might need to add Unsubscribe method to IEventBroker&lt;T&gt; if you prefer to leave it.

Second method (the one I would prefer) is better suited for application-wide events since it moves the responsibility of subscription to the infrastructure thus avoiding multiple subscriptions and memory leaks (comparing to first option). It is also easier to unit-test since part of responsibilities are taken away from subscriber.

Update based on question update: Publishing messages also looks good. In this case (following my suggestion to leave only second method of event subscription) I would remove Subscribe method from IEventBroker&lt;T&gt; declaration, and refactor it to non-generic IEventPublisher interface with generic method void Publish&lt;T&gt;(T eventToPublish).