c# - 简单注入(inject)器 - RegisterCollection 和 RegisterDecorator 使用 Composite 模式和接口(interface)继承

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

如何将类型注册为 IPollingService<TContext>这样它们就可以通过 container.RegisterDecorator(typeof(IPollingService<>), typeof(ContextAwarePollingServiceDecorator<>)) 进行装饰, 但也将它们注册为 IPollingService 的集合这样它们就会被注入(inject)到 CompositePollingService 的构造函数中通过container.RegisterCollection(typeof(IPollingService), types)

我有以下接口(interface):

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 的集合这样它们就会被注入(inject)我的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);

关于c# - 简单注入(inject)器 - RegisterCollection 和 RegisterDecorator 使用 Composite 模式和接口(interface)继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49903476/

相关文章:

c# - 字符串模式查找字符

c# - mysql数据库关系问题

c# - Linq2SQL 按运行时已知的属性分组

c# - 异步等待 Task.FromResult(0)

dependency-injection - 有状态对象(非全局)的 IoC 依赖注入(inject)

c# - .NET 核心异常 : A circular dependency was detected for the service of type

c# - 来自特定程序集的 Unity DI 自动注册

android - 如何将 AndroidInjector 与子组件一起使用

mvvm - Autofac MVVM-终身

asp.net-mvc - 使用 IoC,Singleton 可以注入(inject)具有 transient 生命周期的对象吗?