我有一个场景,我有两个班级,让我们称他们为SingletonWorker
和ScopedWorker
,分别注册了Singleton和Scoped生活方式。两者都依赖于IMetricSubmitter
的构造函数。工作人员使用IMetricSubmitter
将指标作为其逻辑的一部分提交。 IMetricSubmitter
有一个名为DefaultMetricSubmitter
的单例实现,为了EnrichMetricsDecorator
依赖,我想用ScopedWorker
进行修饰,以便SingletonWorker
最终得到DefaultMetricSubmitter
ScopedWorker
和EnrichMetricsDecorator
将以DefaultMetricSubmitter
装饰var singleton = new SingletonWorker(
new DefaultMetricSubmitter());
var scoped = new ScopedWorker(
new EnrichMetricsDecorator(
new DefaultMetricSubmitter()));
结束。有没有办法今天使用SimpleInjector创建这样的注册?
对象图基本上应如下所示:
RegisterConditional
对我来说,将RegisterDecorator
与一个知道消费者的谓词组合在一起,LifetimeScope
就是注册装饰器的方法,但我不知道怎么办将两者结合起来。理想情况下,我希望为装饰器注册一个条件,该条件基于在请求作为消费构造函数的依赖项时是否存在活动作用域,并且在这种情况下为该活动作用域创建装饰器实例。出于辩论的目的,范围可以假设为^.*(S[A-Z0-9]{7})(?!=[A-Z0-9]).*$
。
答案 0 :(得分:1)
使用RegisterDecorator
方法无法实现您的目标。相反,您将不得不恢复使用RegisterConditional
方法。考虑到您的给定对象图,这些注册应如下所示:
container.Register<ScopedWorker>(Lifestyle.Scoped);
container.Register<SingletonWorker>(Lifestyle.Singleton);
container.RegisterConditional<IMetricSubmitter, EnrichMetricsDecorator>(
Lifestyle.Scoped,
c => c.Consumer.ImplementationType == typeof(ScopedWorker));
container.RegisterConditional<IMetricSubmitter, DefaultMetricSubmitter>(
Lifestyle.Singleton,
c => c.Consumer.ImplementationType == typeof(EnrichMetricsDecorator));
文档中描述了here。
<强>更新强>
使用更新后的对象图(包含额外的单件装饰器),注册可能如下所示:
// Useful helper method
static bool InjectedInto<TConsumer>(PredicateContext c) =>
c.Consumer.ImplementationType == typeof(TConsumer);
container.Register<ScopedWorker>(Lifestyle.Scoped);
container.Register<SingletonWorker>(Lifestyle.Singleton);
container.RegisterConditional<IMetricSubmitter, DefaultMetricSubmitter>(
Lifestyle.Singleton,
InjectedInto<CachingMetricSubmitterDecorator>);
container.RegisterConditional<IMetricSubmitter, CachingMetricSubmitterDecorator>(
Lifestyle.Singleton,
c=> !InjectedInto<ScopedWorker>(c)&&!InjectedInto<CachingMetricSubmitterDecorator>(c));
container.RegisterConditional<IMetricSubmitter, EnrichMetricsDecorator>(
Lifestyle.Scoped,
InjectedInto<ScopedWorker>);