我在 Autofac(v4.4.0、.NET 4.6.1)中遇到了一些意外行为,我认为这可能是一个错误。
来自documentation :
Default Registrations
If more than one component exposes the same service, Autofac will use the last registered component as the default provider of that service:
例如如果我这样做:
builder.RegisterType<FooOne>().As<IFoo>();
// Next line replaces default IFoo implementation
builder.RegisterType<FooTwo>().As<IFoo>();
我期望(并获得)一个 FooTwo
的实例当我解决 IFoo
来自容器。
但是,如果我已经注册了一个 IFoo
,我使用 RegisterDecorator<T>
注册 IFoo
装饰器的函数,它不会替换 IFoo
的默认注册.例如:
// Register FooOne directly
builder.RegisterType<FooOne>().As<IFoo>(); // (1)
// Now set up a decorator
builder.RegisterType<FooOne>().Named<IFoo>("foo");
builder.RegisterDecorator<IFoo>((c, inner) =>
new DecoratorFoo(inner), fromKey: "foo");
将解决 IFoo
作为未修饰 FooOne
.这对我来说是不一致的;违反principle of least astonishment .
你可能会说我根本不应该有第 (1) 行(没有它代码也能正常工作)——但它是一个公认的习惯用法(例如 here )使用插件来替换注册。
在我的例子中,这个错误出现在一个相当大的代码库中,其中包装类型已经按照惯例注册,现在需要装饰,需要重新考虑如何注册。
适用于 LINQPad 的要点演示了该问题是 here .
是否有任何设计原因导致我遗漏的观察到的行为?有没有办法让装饰器注册替换默认值?
最佳答案
您可以看到关于您的问题的未解决问题 here .在那里的讨论中,您可以找到这种行为背后的原因。据我所知,他们正试图解决这个问题,但由于 autofac 的内部工作原理,结果证明这并不是一件小事。
与此同时,作为一种解决方法,您可以像这样注册您的装饰器:
builder.Register((cnt, parameters) => new DecoratorFoo(cnt.ResolveNamed<IFoo>("foo", parameters))).As<IFoo>();
这也将解决另一个问题\错误(在此 stackoverflow question 中提到),您以后可能会遇到(或不会)与装饰器不会将参数传播到装饰对象这一事实有关。
关于c# - 在 Autofac 中,如何用装饰器替换默认注册?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43168536/