繁体   English   中英

在 Simple Injector 中有条件地注册集合

[英]Conditionally register collection in Simple Injector

我想根据消费者是谁有条件地将类型注册到集合中。 就像是:

Container.Collection.RegisterConditionally(
    typeof(IEventHandler<>),
    myPublisherTypes, 
    c => c.Consumer.ImplementationType == typeof(PublishEventDecorator<,>));

Container.Collection.RegisterConditionally(
    typeof(IEventHandler<>),
    myTypes, 
    c => c.Consumer.ImplementationType != typeof(PublishEventDecorator<,>));

场景是我希望将某些类型的IEventHandler<>作为集合在PublishEventDecorator的构造函数中解析; IEnumerable<IEventHandler<TEvent>> 并且 rest 在其他任何地方被请求解决。

这可能吗?

尽管 Simple Injector 包含几个允许您有条件地注册 collections 的功能,但它缺少任何开箱即用的功能,允许您在 collections 的开放通用抽象上执行此操作。

但是有办法解决这个问题。 例如,您可以将InstanceProducer实例列表注入装饰器。 这将导致如下所示的注册:

Container.Register(typeof(IPublishEvent<>), typeof(PublishEvent<>));
Container.RegisterDecorator(typeof(IPublishEvent<>), typeof(PublishEventDecorator<>));
Container.Collection.Register(typeof(IEventHandler<>), myTypes);

// Create a list of InstanceProducer instances for the list of publisher types.
// InstanceProducers are Simple Injector's registration factories. They are used
// to resolve instances from the container.
InstanceProducer[] myPublisherTypesProducers = (
    from implementation in myPublisherTypes
    from service in implementation.GetClosedTypesOf(typeof(IEventHandler<>))
    select Lifestyle.Transient.CreateProducer(service, implementation, Container))
    .ToArray();

// This conditional registration injects the instance producers into the decorator.
Container.RegisterConditional<InstanceProducer[]>(
    Lifestyle.Singleton.CreateRegistration(
        typeof(InstanceProducer[]), myPublisherTypesProducers, Container),
    c => c.Consumer.ImplementationType
        .GetClosedTypesOf(typeof(PublishEventDecorator<>)).Any());

此注册的结果是您需要专门制作装饰器,因为它需要依赖于InstanceProducer实例列表。 有了它,它开始依赖于 Simple Injector。 因此,将装饰器移动到您的Composition Root中是一种很好的做法。 这是它可能的实现:

public class PublishEventDecorator<T> : IPublishEvent<T>
{
    private readonly IPublishEvent<T> decoratee;
    private readonly InstanceProducer[] handlerProducers;

    public PublishEventDecorator(
        IPublishEvent<T> decoratee, InstanceProducer[] handlerProducers)
    {
        this.decoratee = decoratee;
        this.handlerProducers = handlerProducers;
    }

    private IEnumerable<IEventHandler<T>> Handlers =>
        from producer in this.handlerProducers
        where producer.ServiceType == typeof(IEventHandler<T>)
        select (IEventHandler<T>)producer.GetInstance();

    public void Publish(T @event)
    {
        // Do something with handlers
        foreach (var handler in this.Handlers) { }

        // Invoke decoratee.
        this.decoratee.Publish(@event);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM