简单注入器 - RegisterCollection 和 RegisterDecorator 使用 Composite 模式和接口继承

Simple Injector - RegisterCollection and RegisterDecorator using Composite pattern and interface inheritance

如何将类型注册为 IPollingService<TContext> 以便它们可以通过 container.RegisterDecorator(typeof(IPollingService<>), typeof(ContextAwarePollingServiceDecorator<>)) 进行装饰,同时将它们注册为 IPollingService 的集合以便它们将被注入通过 container.RegisterCollection(typeof(IPollingService), types)?

进入 CompositePollingService 的构造函数

我有以下接口:

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>,但我将它们作为 IEnumerable<IPollingService> 传递给 CompositePollingService 构造函数,因为会有 [= =15=],而 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 实现中?

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

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);