I posed the question here: Raise domain events for multiple subscribers , and the answer led me to the following template where I can have IEventPublisher:
public interface IEventPublisher<T> { void Publish(T data); }
and IEventSubscriber:
public interface IEventSubscriber<T> { void Handle(T data); }
The problem is that I need to pass an instance of each publisher to the constructor, for example:
public Service(IEventPublisher<ThingyChangedEvent> publisherThingyChanged) { // Set publisher to local variable } // then call this in a method _publisherThingyChanged.Publish(new ThingyChangedEvent { ThingyId = model.Id});
Ideally, I would like to have a universal publisher that contains any IEventPublishers, so I can call somthing like:
_genericPublisher.Publish(new ThingyChangedEvent { ThingyId = model.Id});
I cannot figure out how to do this, although I cannot pass the IEventPublisher collection without defining T, as in this example, as ThingyChangedEvent, whereas I want to determine the publisher based on the type that the common publisher is passed to.
Any suggestions that are very much appreciated.
EDIT:
OK, using the answer below and some information from here: http://www.udidahan.com/2009/06/14/domain-events-salvation/ I came up with the following, but this is not entirely true:
public interface IEventManager { void Publish<T>(T args) where T : IEvent; }
public class EventManager: IEventManager {Autofac.ILifetimeScope _container;
public EventManager(Autofac.ILifetimeScope container) { _container = container; }
}
Now I can take an instance of IEventManager eventManager in the constructor allowed by autofac and call it like this:
_eventManager.Publish<ThingyChangedEvent>(new ThingyChangedEvent() { ThingyId = Guid.NewGuid() });
Here's what I don't like about this solution:
I do not want to take an instance of ILifetimeScope in the constructor, I want to be able to take the IEventSubscribersProvider collection, but autofac will not solve this if I ask to say:
IEnumerable<IEventSubscribersProvider<IEvent>>
I can only enable it if I pass in the publication type and call:
Resolve<IEventSubscribersProvider<T>>.
The second problem is not a huge deal, but it would be nice to be able to invoke the publication without passing it in the same way:
_eventManager.Publish(new ThingyChangedEvent() { ThingyId = Guid.NewGuid() });
I think if anyone has any suggestions for solving these two problems, in particular, question 1, because I donโt like to add Autofac dependency to different projects. The only thing I can come up with is a manager class that explicitly accepts what I need:
public SomeConstructor( IEventSubscribersProvider<ThingyChangedEvent> thingChangedSubscribeProviders, IEventSubscribersProvider<SomeOtherEvent> someOtherSubscribeProviders, etc....) {
Thanks so much for any suggestions.
EDIT 2
After doing a lot of research and looking at this Autofac Generic Service solution at runtime, I'm not sure I can achieve what I want. The best solution I can come up with is the following:
public interface IEventSubscribersProviderFactory : Amico.IDependency { IEventSubscribersProvider<T> Resolve<T>() where T : IEvent; } public class EventSubscribersProviderFactory : IEventSubscribersProviderFactory { Autofac.ILifetimeScope _container; public EventSubscribersProviderFactory(Autofac.ILifetimeScope container) { _container = container; } public IEventSubscribersProvider<T> Resolve<T>() where T : IEvent { return _container.Resolve<IEventSubscribersProvider<T>>(); } }
And then the EventManager will take the IEventSubscribersProviderFactory in the constructor to remove the Autofac dependency from this project.
I will go with it for now, but I hope it finds a better solution in the long run.