c# – SimpleInjector如何为单个通用实现注册多个开放通用接口

前端之家收集整理的这篇文章主要介绍了c# – SimpleInjector如何为单个通用实现注册多个开放通用接口前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试使用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);
            }
        }
    };
}

猜你在找的C#相关文章