I am looking into how an event aggregator can be implemented directly in the DI container and struggling how to do that with DryIoC.
I have the following example services and contracts for the event aggregation:
public class EventHub<T> : IPublisher<T>, ISubscriber<T>
{
private List<Action<T>> listeners = new List<Action<T>>();
public void Publish(T data)
{
foreach (var listener in listeners)
{
listener(data);
}
}
public void Register(Action<T> listener)
{
listeners.Add(listener);
}
public void Unregister(Action<T> listener)
{
listeners.Remove(listener);
}
}
public interface IPublisher<T>
{
void Publish(T data);
}
public interface ISubscriber<T>
{
void Register(Action<T> listener);
void Unregister(Action<T> listener);
}
Now, if someone resolves a publisher or subscriber for a specific type, I would like the DI container to always return the same event hub.
I tried multiple registrations of the EventHub
class, but all of them have their specific problems:
Separate registrations
Container.Register(typeof(IPublisher<>), typeof(EventHub<>), Reuse.Singleton);
Container.Register(typeof(ISubscriber<>), typeof(EventHub<>), Reuse.Singleton);
The problem here is that DryIoC does not couple the registrations, i.e. for each type there will be two implementations.
Registration mapping
Container.Register(typeof(EventHub<>), typeof(EventHub<>), Reuse.Singleton);
Container.RegisterMapping(typeof(IPublisher<>), typeof(EventHub<>));
Container.RegisterMapping(typeof(ISubscriber<>), typeof(EventHub<>));
DryIoC (v2.12.10) does not support that and throws an error message when trying to register the first open generic mapping.
RegisterMany
Container.RegisterMany(new [] {typeof(IPublisher<>), typeof(ISubscriber<>)}, typeof(EventHub<>), Reuse.Singleton);
This actually works, but still resolves different instances for publishers and subscribers.
Is there a way to make this behavior work?