patterncsharpMinor
Loosely coupled application wide events
Viewed 0 times
applicationeventswidelooselycoupled
Problem
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:
All events are classes derived from
Essentially I provide two ways to subscribe to events:
Subscribe by setting a dependency on (one or more) IEventBroker<>
Subscribe by implementing (one or more) IEventSubscriber<>
Any more or less obvious pitfalls? Suggestions?
Side note:
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<> (where T : EventBase) will be automatically registered in the container. My DefaultEventBroker implementation then has an optional IEnumerable> dependency, which the container will resolve to all visible subscribers for a given event type. Under the hood a System.Reactive.Subjects.Subject<> (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<>
public class MyEventListeningComponent
{
public MyEventListeningComponent(IEventBroker eventBroker)
{
eventBroker.Subscribe(e =>
{
Console.WriteLine("[MyEventListeningComponent] Program Started: {0}", e.StartDate.ToString());
});
}
}Subscribe by implementing (one or more) IEventSubscriber<>
public class MyEventSubscriber : IEventSubscriber, IEventSubscriber
{
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<> is essentially an IObserver<> without the OnCompleted aSolution
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
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
The first method of subscribing (via
IEventBroker 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 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 declaration, and refactor it to non-generic IEventPublisher interface with generic method void Publish(T eventToPublish).Context
StackExchange Code Review Q#20775, answer score: 3
Revisions (0)
No revisions yet.