I'm trying to get started with SimpleInjector as an IOC Container and up to now I'm pretty happy with it. But right now I'm stuck on a problem I can't solve. I searched on SO and in the documentation, but it seems to be not answered yet. I've seen the howto doc from SimpleInjector but that doesn't cover open generic interfaces.
I have two generic interfaces like these:
public interface IEventPublisher<TEvent>
{
void Publish(TEvent Event);
}
public interface IEventSubscriber<TEvent>
{
void Subscribe(Action<TEvent> CallBack);
}
And one open generic implementation for those two:
class EventMediator<T> : IEventPublisher<T>, IEventSubscriber<T>
{
List<Action<T>> Subscriptions = new List<Action<T>>();
public void Publish(T Event)
{
foreach (var Subscription in this.Subscriptions)
Subscription.Invoke(Event);
}
public void Subscribe(Action<T> CallBack)
{
this.Subscriptions.Add(CallBack);
}
}
In my Application I'm setting up SimpleInjector like this:
this.Container = new SimpleInjector.Container();
this.Container.RegisterOpenGeneric(typeof(IEventPublisher<>), typeof(EventMediator<>), Lifestyle.Singleton);
this.Container.RegisterOpenGeneric(typeof(IEventSubscriber<>), typeof(EventMediator<>), Lifestyle.Singleton);
this.Container.Verify();
What I'm trying to archive is: I'd like to get exactly the same instance when asking for a IEventPublisher or an IEventSubscriber. And furthermore this Instance shall be a singleton for any T.
I've tested this with these lines:
class DummyEvent {}
var p = this.Container.GetInstance<IEventPublisher<DummyEvent>>();
var s = this.Container.GetInstance<IEventSubscriber<DummyEvent>>();
var areSame = (object.ReferenceEquals(p,s));
Unfortunatly p and s don't refer to the same instance. Anyone happens to know a solution to this problem?
There are certain solutions for this, here's one: Create separate implementations for
IEventPublisher<T>
andIEventSubscriber<T>
and let them delegate to theEventMediator<T>
. For instance with these implementations:Now you make the registrations as follows:
Now both the
EventPublisher<DummyEvent>
andEventSubscriber<DummyEvent>
will point at the sameEventMediator<DummyEvent>
instance.Another way to achieve this without the extra type is to make use of the
ResolveUnregisteredType
event (which is what theRegisterOpenGeneric
extension method itself uses under the covers). Your configuration would look like this:You could even extract this code into a more general extension method. This way your registration would look like this:
The extension method would look like this: