Search code examples
c#simple-injector

Simple Injector with Domain Events


I'm trying to implement Domain Events into my system, but I'm stuck. I am using SimpleInjector, and I think i'm missing something.

Domain Event:

public static class DomainEvent
{
    public static IEventDispatcher Dispatcher { get; set; }

    public static void Raise<T>(T @event) where T : IDomainEvent
    {
        Dispatcher.Dispatch(@event);
    }

}

SimpleInjectorEventDispatcher

public class SimpleInjectorEventDispatcher : IEventDispatcher
{
    private readonly Container container;
    public SimpleInjectorEventDispatcher(Container container)
    {
        this.container = container;
    }

    public void Dispatch<TEvent>(TEvent eventToDispatch) where TEvent : IDomainEvent
    {
        var handlerType = typeof(IDomainHandler<>).MakeGenericType(eventToDispatch.GetType());
        var handlers = this.container.GetAllInstances(handlerType);

        foreach (dynamic handler in handlers)
        {
            handler.HandleEvent((dynamic)eventToDispatch);
        }
    }
}

SimpleInjector

container.Register<IEventDispatcher, SimpleInjectorEventDispatcher>();

The IEventDispatcher Dispatcher is always null. How do I make sure it is correctly initialised?


Solution

  • The IEventDispatcher Dispatcher is always null.

    Simple Injector will not magically initialize any static members of some random class for you. As long as you didn’t' set this static field yourself at start-up, nobody will.

    I would however urge you to stop using this static DomainEvent class completely. This design is rooted in an old article from Udi Dahan, but he himself abandoned the idea of using static classes for this purpose a long time ago. He is currently advising against it, as am I.

    Static classes are troublesome from the perspective of testability and discoverability. From that perspective, the use of Dependency Injection is a much better alternative.

    The solution to your problem is therefore really straightforward: Remove the static DomainEvents class from your code base and inject the IEventDispatcher into the constructors of consumers that require publishing events.