c# - 在 Autofac 中,如何用装饰器替换默认注册?

标签 c# autofac

我在 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/

相关文章:

c# - Visual C# 方法调用使用过多内存?

c# - 使用 Unity 中的 slider 更改数组中一个 AudioSource 的音量

c# - 与 Autofac 并行运行 xUnit 集成测试时无法加载类型 CaSTLe.Proxies.IReadinessProxy

c# - 使用 MVC ValidationAttribute 进行 Autofac 属性注入(inject)

c# - Autofac 解析不同 AppDomain 中的对象

c# - XmlTextReader 与 XDocument

c# - await httpClient.SendAsync(httpContent) 没有响应

c# - C#中的整数溢出左​​移

c# - 如何使用自定义工厂方法注册开放泛型?

dependency-injection - Autofac 未解决模型绑定(bind)器依赖项