I have an interface.
// Assembly: Common
public interface IEventHandler<TEvent> where TEvent : IDomainEvent
{
void HandleEvent(TEvent theEvent);
}
// Assembly: Common
public interface IDomainEvent
{
}
// Assembly: Common
public interface IEventDispatcher
{
void Register(IEventHandler<IDomainEvent> handler);
void Dispatch(IDomainEvent theEvent);
}
// Assembly: Membership
public sealed class MemberRegistered : IDomainEvent
{
// event properties
}
Then on my ASP MVC 5 project I have event handler for the events.
public sealed class MemberRegisteredHandler : IEventHandler<MemberRegistered>
{
public MemberRegisteredHandler(ApplicationUserManager userManager)
{
this.userManager = userManager;
}
private ApplicationUserManager userManager;
public void HandleEvent(MemberRegistered theEvent)
{
User user = new User(
theEvent.MemberId.ToString(),
theEvent.Username,
theEvent.PersonalInformation.Email);
this.userManager.CreateUserWithRandomPassword(user);
}
}
On my Startup class
var container = new Container();
// TIP: For Simple Injector >= v4.3, instead use container.Collection.Register.
container.RegisterManyForOpenGeneric(
typeof(IEventHandler<>),
container.RegisterAll,
Assembly.GetExecutingAssembly());
container.Register<IEventDispatcher, SimpleEventDispatcher>();
With that, how can I get the event dispatcher
and register all the event handlers into it?
I've tried
var eventDispatcher = container.GetInstance<IEventDispatcher>();
foreach (var handler in container.GetAllInstances<IEventHandler<IDomainEvent>>())
{
eventDispatcher.Register(handler);
}
But its not working. the GetAllInstances method is not returning anything.
Things to note:
The IEventDispatcher
is a dependency on my EF DbContext constructor and I have(right now) two contexts. MembershipContext
and IdentityAccessContext
which both derived from EventDipatchingContext
that derives from DbContext
.
Basically its EventDispatchingContext : DbContext
then MembershipContext : EventDispatchingContext
The EventDispatchingContext
is responsible for delegating the events to the event dispatcher after its Commit() method is invoked
. They are not get fired instantly on my Domain Entites. I got this architecture from Jimmy Bogard's blog
https://lostechies.com/jimmybogard/2014/05/13/a-better-domain-events-pattern/
Do I need to make IEventDispatcher a singleton in this case? Why?
How to properly regsiter the handlers to the event dispatcher?
Prevent 'registering' the event handlers in your event dispatcher. Instead you should make the event dispatcher implementation part of your Composition Root. This way you can safely take a dependency upon the container from within the dispatcher as follows:
public class SimpleInjectorEventDispatcher : IEventDispatcher
{
private readonly Container container;
public SimpleInjectorEventDispatcher(Container container)
{
this.container = container;
}
public void Dispatch(IDomainEvent theEvent)
{
var handlerType =
typeof(IEventHandler<>).MakeGenericType(theEvent.GetType());
var handlers = this.container.GetAllInstances(handlerType);
foreach (dynamic handler in handlers)
{
handler.HandleEvent((dynamic)theEvent);
}
}
}
Do note that the IEventDispatcher
interface now only contains a Dispatch
method.
Do I need to make IEventDispatcher a singleton in this case? Why?
You don't have to make the event dispatcher implementation a singleton, but since it has no dependencies and no state, it's wise to make it a singleton. This way its consumers can become singletons as well. The more singletons the merrier.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With