如何将类型注册为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
实现中?
您可以使用以下代码执行此操作:
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);