I have a WCF service that uses Simple Injector for dependency injection. I want to wire up some event handlers in the container bootstrapper. I have created an interface IStatusChangeNotification
:
public interface IStatusChangeNotification
{
event EventHandler<int> JobStatusChange;
}
My CommandHandler
implements IStatusChangeNotification
and there are two event handler classes EmailNotification
and MmrNotification
, each defining a Notify()
method. Then in my bootstrap code I have the following:
container.Register<EmailNotification>();
container.Register<MmrNotification>();
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
Assembly.GetExecutingAssembly());
container.RegisterInitializer<IStatusChangeNotification>(scn =>
{
scn.JobStatusChange += container.GetInstance<EmailNotification>().Notify;
scn.JobStatusChange += container.GetInstance<MmrNotification>().Notify;
});
This works and the notifications are received. My question is whether this is the correct/best approach for wiring up event handlers? How do I remove the handlers at the end of the request and will failing to remove them result in a memory leak?
Although your approach might work, I think this part of your system design might deserve the same amount of attention as your command handlers do. The most common reason for command handlers to trigger events, is to publishing events that describe some business related action. So instead of using .NET events, model those domain events the same way as you model your commands:
With the previous infrastructure, you can create the following event and command handlers:
Now you can register your command handlers and event handlers as follows:
This removes the need to register each event handler class seperately, since they are simply implementations of
IEventHandler<JobStatusChanged>
and can all be batch-registered in one line of code. There's also no need to useRegisterInitializer
to hook any events using custom defined interfaces.Other advantages of this are:
IEventPublisher
interface makes it very clear that this command is publishing events.SimpleInjectorEventProcessor
. For instance, you can deside to run them in parallel, run them in their own transaction, process them later (by storing them in an event store).