我正在尝试使用SimpleInjector作为IOC容器,到目前为止我对此非常满意.但是现在我遇到了一个我无法解决的问题.我搜索了SO和文档,但似乎还没有回答.我见过
the howto doc from SimpleInjector,但不包括开放的通用接口.
我有两个这样的通用接口:
public interface IEventPublisher<TEvent> { void Publish(TEvent Event); } public interface IEventSubscriber<TEvent> { void Subscribe(Action<TEvent> CallBack); }
这两个开放的通用实现:
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); } }
在我的应用程序中,我正在设置SimpleInjector,如下所示:
this.Container = new SimpleInjector.Container(); this.Container.RegisterOpenGeneric(typeof(IEventPublisher<>),typeof(EventMediator<>),Lifestyle.Singleton); this.Container.RegisterOpenGeneric(typeof(IEventSubscriber<>),Lifestyle.Singleton); this.Container.Verify();
我想要存档的是:
在要求IEventPublisher或IEventSubscriber时,我想获得完全相同的实例.此外,此实例应为任何T的单例.
我用这些线测试了这个:
class DummyEvent {} var p = this.Container.GetInstance<IEventPublisher<DummyEvent>>(); var s = this.Container.GetInstance<IEventSubscriber<DummyEvent>>(); var areSame = (object.ReferenceEquals(p,s));
不幸的是,p和s并没有引用相同的实例.有人碰巧知道这个问题的解决方案吗?
解决方法
对此有一些解决方案,这里是一个:为IEventPublisher创建单独的实现< T>和IEventSubscriber< T>并让他们委托给EventMediator< T>.例如,使用这些实现:
public class EventPublisher<TEvent> : IEventPublisher<TEvent> { private readonly EventMediator<TEvent> mediator; public EventPublisher(EventMediator<TEvent> mediator) { this.mediator = mediator; } public void Publish(TEvent Event) { this.mediator.Publish(Event); } } public class EventSubscriber<TEvent> : IEventSubscriber<TEvent> { private readonly EventMediator<TEvent> mediator; public EventSubscriber(EventMediator<TEvent> mediator) { this.mediator = mediator; } public void Subscribe(Action<TEvent> CallBack) { this.mediator.Subscribe(Callback); } }
现在您进行如下注册:
container.RegisterSingleOpenGeneric(typeof(EventMediator<>),typeof(EventMediator<>)); container.RegisterSingleOpenGeneric(typeof(IEventPublisher<>),typeof(EventPublisher<>)); container.RegisterSingleOpenGeneric(typeof(IEventSubscriber<>),typeof(EventSubscriber<>));
现在两个EventPublisher< DummyEvent>和EventSubscriber< DummyEvent>将指向相同的EventMediator< DummyEvent>实例.
在没有额外类型的情况下实现此目的的另一种方法是使用ResolveUnregisteredType事件(这是RegisterOpenGeneric扩展方法本身在封面下使用的事件).您的配置如下所示:
container.RegisterSingleOpenGeneric(typeof(EventMediator<>),typeof(EventMediator<>)); container.ResolveUnregisteredType += (s,e) => { if (e.UnregisteredServiceType.IsGenericType) { var def = e.UnregisteredServiceType.GetGenericTypeDefinition(); if (def == typeof(IEventPublisher<>) || def == typeof(IEventSubscriber<>)) { var mediatorType = typeof(EventMediator<>) .MakeGenericType(e.UnregisteredServiceType.GetGenericArguments()[0]); var producer = container.GetRegistration(mediatorType,true); e.Register(producer.Registration); } } };
您甚至可以将此代码提取到更通用的扩展方法中.这样您的注册将如下所示:
container.RegisterSingleOpenGeneric(typeof(EventMediator<>),typeof(EventMediator<>)); container.ForwardOpenGenericTo(typeof(IEventPublisher<>),typeof(EventMediator<>)); container.ForwardOpenGenericTo(typeof(IEventSubscriber<>),typeof(EventMediator<>));
扩展方法如下所示:
public static void ForwardOpenGenericTo(this Container container,Type openGenericServiceType,Type openGenericServiceTypeToForwardTo) { container.ResolveUnregisteredType += (s,e) => { var type = e.UnregisteredServiceType; if (type.IsGenericType) { if (type.GetGenericTypeDefinition() == openGenericServiceType) { var forwardToType = openGenericServiceTypeToForwardTo.MakeGenericType( type.GetGenericArguments()); var producer = container.GetRegistration(forwardToType,true); e.Register(producer.Registration); } } }; }