如何使用Simple Injector根据消费者的生活方式有条件地注册装饰器?

时间:2016-06-21 08:28:50

标签: c# dependency-injection simple-injector

我有一个场景,我有两个班级,让我们称他们为SingletonWorkerScopedWorker,分别注册了Singleton和Scoped生活方式。两者都依赖于IMetricSubmitter的构造函数。工作人员使用IMetricSubmitter将指标作为其逻辑的一部分提交。 IMetricSubmitter有一个名为DefaultMetricSubmitter的单例实现,为了EnrichMetricsDecorator依赖,我想用ScopedWorker进行修饰,以便SingletonWorker最终得到DefaultMetricSubmitter ScopedWorkerEnrichMetricsDecorator将以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]).*$

1 个答案:

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