加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 08:45:17 所属栏目:百科 来源:网络整理
导读:我正在尝试使用SimpleInjector作为IOC容器,到目前为止我对此非常满意.但是现在我遇到了一个我无法解决的问题.我搜索了SO和文档,但似乎还没有回答.我见过 the howto doc from SimpleInjector,但不包括开放的通用接口. 我有两个这样的通用接口: public interf
我正在尝试使用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);
            }
        }
    };
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读