简单的注射器。如何使用 Scoped 生活方式在对象的装饰器链中多次重用装饰器 class

Simple Injector. How to reuse a decorator class more than once in object's decorator chain using Scoped lifestyle

我想在像这样的装饰对象链中多次重复使用相同的 class。

InstrumentedTargetDecorator -> ResilientTargetDecorator -> InstrumetedTargetDecorator -> Target

请注意,InstrumentedTargetDecorator 在这里有意使用了两次。

这就是 SimpleInjector 语法看起来如何连接上面的内容

container.Register<ITarget, Target>(Lifestyle.Scoped);
container.RegisterDecorator(
    typeof(ITarget), typeof(InstrumentationTargetDecorator), Lifestyle.Scoped);
container.RegisterDecorator(
    typeof(ITarget), typeof(ResilienceTargetDecorator), Lifestyle.Scoped);
container.RegisterDecorator(
    typeof(ITarget), typeof(InstrumentationTargetDecorator), Lifestyle.Scoped);

如果 运行 与标准选项一样,这将引发以下警告

-[Ambiguous Lifestyles] The registration for ITarget (Async Scoped) maps to the same implementation (InstrumentationTargetDecorator) as the registration for ITarget (Scoped) does, but the registration maps to a different lifestyle. This will cause each registration to resolve to a different instance.

-[Ambiguous Lifestyles] The registration for ITarget (Scoped) maps to the same implementation (InstrumentationTargetDecorator) as the registration for ITarget (Async Scoped) does, but the registration maps to a different lifestyle. This will cause each registration to resolve to a different instance.

(报告了 2 条警告消息,因为 InstrumentationTargetDecorator 有 2 个装饰器注册)

我真正能让它工作的唯一方法是 not 运行ning .Verify() (并将 EnableAutoVerification 设置为 false).不用说,这在实践中不是一个可行的选择。

对于单个装饰器注册,似乎没有任何方法可以抑制此警告,因为常规抑制警告剧本对装饰器不起作用,即装饰器注册在注册时实际上无法检索,例如

Container.GetRegistration<ITarget>() 生成 original/non-decorated 实例(我怀疑这是因为在构建对象图之前装饰器并没有真正解析)

如果我尝试强制构建图形

Container.Verify(VerificationOption.VerifyOnly);

var registration = Container.GetRegistration<ITarget>()?.Registration;
registration?.SuppressDiagnosticWarning(DiagnosticType.AmbiguousLifestyles, "I'm right");

Container.Verify();

我可以把手放在最外面的 InstrumentationTargetDecorator 上,这样我就可以抑制一条警告消息,但不能抑制另一条。


更多上下文和下面的实际程序

原来我是这样设置的

ResilientTargetDecorator -> Target

(ResilientTargetDecorator 包裹 Target)

然后我决定测量Target方法调用需要多长时间,所以我引入了一个新的装饰器

ResilientTargetDecorator -> InstrumetedTargetDecorator -> Target

到目前为止一切顺利,按预期工作。

但是,如果我现在想重新使用该检测装饰器来测量包括弹性目标装饰器在内的整个链需要多长时间怎么办?


在此处重现此问题的程序

https://dotnetfiddle.net/zESxqc

您在 Simple Injector 中遇到了错误。 我将尝试在下一个补丁版本中修复此问题。此错误已在 v5.3.3 中修复。

作为变通方法,在旧版本中工作时,在您的组合根中创建装饰器的衍生产品,并使该衍生产品成为第二次注册。希望这会抑制无效警告:

class Derivative: InstrumentationTargetDecorator { ...}


container.Register<ITarget, Target>(Lifestyle.Scoped);
 container.RegisterDecorator(typeof(ITarget), typeof(InstrumentationTargetDecorator), Lifestyle.Scoped);
 container.RegisterDecorator(typeof(ITarget), typeof(ResilienceTargetDecorator), Lifestyle.Scoped);
 container.RegisterDecorator(typeof(ITarget), typeof(Derivative), Lifestyle.Scoped);