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

时间:2018-04-18 15:23:00

标签: c# dependency-injection ioc-container simple-injector

如何将类型注册为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>构造函数中,因为它会混合{ {1}},而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实现中?

1 个答案:

答案 0 :(得分: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);