4

我正在使用 Autofac 来处理我的应用程序中的依赖注入。为了不必明确地进行每一次注册,我首先使用RegisterAssemblyTypes().AsImplementedInterfaces()然后只处理那些需要特别配置的。

我有一个名为的接口IToolStripPopulator,它有几个不同的实现,其中几个正在使用,但有些不再使用(因为我正在努力工作并遵守 OCP,如果我需要不同的功能,我通常不会更改它们,而是不要管它们,然后创建新的来满足我现在的需要)。出于这个原因,我需要通过两种方式覆盖接口的自动注册:

  • 一种实现是注入到我的主要逻辑中,并充当其他一些实现的装饰器。我自然希望通过它注册As<IToolStripPopulator>()并完成它,因为这是我的应用程序功能当前依赖的实现。
  • 那些其他实现是仅在该装饰器类中使用的“内部”填充器。要注入它们,有两种方法:
    • 使用特定类型显式连接外部实现的构造函数;这不是很好,还因为该构造函数必须采用我现在正在使用的内部填充器的确切数量这不符合 OCP。
    • 让外部实现采用IEnumerable<IToolStripPopulator>; 这是我想做的,但这也是我卡住的地方。

我不能让 AutofacIEnumerable自己解决这个问题,因为它只会解决接口的所有实现,即使是我不再使用的接口以及我不想要的“外部”(以及可能会在解析过程中导致无限循环)。

所以我想做的是:

// the inner populators
builder.RegisterType<BrowsersMenuPopulator>().Named<IToolStripPopulator>("inner");
builder.RegisterType<ThreadsafeConnectionMenuPopulator>().Named<IToolStripPopulator>("inner");

// the decorator implementation
builder.RegisterType<BrowserAndConnectionMenuPopulator>().As<IToolStripPopulator>().WithParameter( ? );

但此时无法实际访问现有注册。

4

2 回答 2

7

....在这里,我又尝试了一件我实际上没想到会奏效的东西,但它确实奏效了。

builder.Register(c => c.ResolveNamed<IEnumerable<IToolStripPopulator>>("inner")).As<IEnumerable<IToolStripPopulator>>();

正如我所预料的那样,不会尝试解析IEnumerable<IToolStripPopulator>名为“inner”的注册,而是解析名为“inner”IEnumerableIToolStripPopulator注册——完全符合我的需要。

然后,这将被正确地解决并注入到装饰器实现中,只需注册As<IToolStripPopulator>()而无需进一步配置。

从形式上看,我实际上更希望能够说明直接使用装饰器注册解析的名称,因为这样会更直观和灵活(如果我需要解析几个IEnumerable<IToolStripPopulator>呢?),但在很多情况下,这应该是足够。

@codinghorror 的“橡皮鸭问题解决”概念支配着我的每个工作日....

于 2012-06-16T02:28:18.140 回答
0

直接指定我知道的唯一方法是直接在您的注册码中“新建”:

//decorator impl
builder.Register(c => new BrowserAndConnectionMenuPopulator(c.ResolveNamed<IEnumerable<IToolStripPopulator>>("inner"),...)).As<IToolStripPopulator>();

这具有在注册中直接指定所需的确切依赖项的优点,但缺点是在重新配置BrowserAndConnectionMenuPopulator的依赖项中失去灵活性。为了完整起见,我将其包括在内,但老实说,我更喜欢您发现的解决方案。

于 2012-06-27T15:11:15.107 回答