我在 Autofac(v4.4.0,.NET 4.6.1)中遇到了一些意想不到的行为,我觉得这可能是一个错误。
从文档:
默认注册
如果多个组件公开相同的服务,Autofac 将使用最后注册的组件作为该服务的默认提供者:
例如,如果我这样做:
builder.RegisterType<FooOne>().As<IFoo>();
// Next line replaces default IFoo implementation
builder.RegisterType<FooTwo>().As<IFoo>();
Run Code Online (Sandbox Code Playgroud)
我期望(并获得)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");
Run Code Online (Sandbox Code Playgroud)
将解析IFoo为未修饰的 FooOne. 这让我感觉不一致;违反了最小惊讶原则。
您可能会声称我根本不应该使用第 (1) 行(如果没有它,代码也能正常工作)——但使用插件来替换注册是一种公认的习惯用法(例如此处)。
在我的例子中,这个错误在一个相当大的代码库中表现出来,其中包装类型已经通过约定注册,现在需要进行装饰,需要重新考虑如何完成注册。
适合LINQPad演示该问题,要旨是在这里。
我缺少的观察到的行为是否有任何设计原因?有没有办法让装饰器注册替换默认值?
您可以在此处查看有关您的问题的未解决问题。在讨论中,您可以找到这种行为背后的原因。据我所知,他们正试图解决这个问题,但事实证明,由于 autofac 的内部工作原理,这并不是一件小事。
同时,作为一种解决方法,您可以像这样注册装饰器:
builder.Register((cnt, parameters) => new DecoratorFoo(cnt.ResolveNamed<IFoo>("foo", parameters))).As<IFoo>();
Run Code Online (Sandbox Code Playgroud)
这也将修复另一个问题\错误(在这个stackoverflow question 中提到),您稍后可能会遇到(或不会),与事实相关的装饰器不会将参数向前传播到装饰对象。
| 归档时间: |
|
| 查看次数: |
1420 次 |
| 最近记录: |