Simple Injector - 使用Composite模式和接口继承的RegisterCollection和RegisterDecorator

问题描述 投票:2回答:1

如何将类型注册为IPollingService<TContext>,以便它们将通过container.RegisterDecorator(typeof(IPollingService<>), typeof(ContextAwarePollingServiceDecorator<>))进行装饰,还将它们注册为IPollingService的集合,以便它们将通过CompositePollingService注入container.RegisterCollection(typeof(IPollingService), types)的构造函数中?

我有以下接口:

public interface IPollingService { Task Poll(); }
public interface IPollingService<TContext> : IPollingService
    where TContext : CustomContext { TContext Context { get; } }

和IPollingService的复合模式实现:

class CompositePollingService : IPollingService
{
    private readonly IEnumerable<IPollingService> _pollingServices;

    public CompositePollingService(IEnumerable<IPollingService> pollingServices) => 
        _pollingServices = pollingServices;

    public async Task Poll() => 
        await Task.WhenAll(_pollingServices.Select(s => s.Poll()));
}

我所有的IPollingService的其他实现实际上实现了IPollingService<TContext>,但我将它们作为CompositePollingService传递给IEnumerable<IPollingService>构造函数,因为将有IPollingService<TContext>的混合,而CompositeService只需要了解IPollingService.Poll()

我根据配置有条件地将类型添加到列表中,并使用列表为CompositePollingService的构造函数注册集合:

List<Type> types = new List<Type>();
if (// config says to use TEST Context)
   types.Add(typeof(PollingService<TestContext>)); // impl. of IPollingService<TContext>
if (// config says to use LIVE Context)
   types.Add(typeof(PollingService<LiveContext>)); // impl. of IPollingService<TContext>

container.RegisterCollection(typeof(IPollingService), types);

我有IPollingService<TContext>的装饰师:

class ContextAwarePollingServiceDecorator<TContext>
    : IPollingService<TContext> where TContext: CustomContext
{
    private readonly IPollingService<TContext> _decoratee;

    public ContextAwarePollingServiceDecorator(IPollingService<TContext> decoratee) 
        => _decoratee = decoratee;

    public async Task Poll() {
        // decoration here...
        await _decoratee.Poll(cancellationToken);
    }

    public TContext Context => _decoratee.Context;
}

但是,当我像这样注册时,我的装饰器不适用于我的IPollingService<TContext>实现:

container.RegisterDecorator(typeof(IPollingService<>),
    typeof(ContextAwarePollingServiceDecorator<>));

我如何将类型注册为IPollingService<TContext>,但也将它们注册为IPollingService的集合,以便将它们注入我的CompositePollingService实现中?

c# dependency-injection ioc-container simple-injector
1个回答
1
投票

您可以使用以下代码执行此操作:

var ls = Lifestyle.Transient;

// Create a collection of InstanceProducer instances for IPollingService<T> registrations
var producers = new InstanceProducer[]
{
   ls.CreateProducer<IPollingService<TestContext>, PollingService<TestContext>>(container),
   ls.CreateProducer<IPollingService<LiveContext>, PollingService<LiveContext>>(container),
};

// Register a decorator that wraps around all IPollingService<T> instances
container.RegisterDecorator(typeof(IPollingService<>),
    typeof(ContextAwarePollingServiceDecorator<>));

// Register the IEnumerable<IPollingService> that contains all IPollingService<T> instances
container.RegisterInstance(producers.Select(p => (IPollingService)p.GetInstance()));

// Register the composite
container.Register<IPollingService, CompositePollingService>(Lifestyle.Singleton);
© www.soinside.com 2019 - 2024. All rights reserved.