Autofac-在运行时解析实现同一接口的一个或多个类型

时间:2019-01-06 08:32:05

标签: c# xamarin.forms autofac

我对使用IoC / DI并不陌生,我正在学习有关Autofac的知识,以便在我的Xamarin Form C#项目中使用它。我正在阅读Autofac文档(https://autofac.readthedocs.io/en/latest/getting-started/index.html#application-execution),并对与“应用程序执行”部分有关的声明感到困惑,该声明的内容为:

稍后,如果您希望您的应用程序写一个不同的日期,则可以实现一个不同的IDataWriter,然后在启动时更改注册。...

对此我感到困惑,因为它表示如果我想要不同的IDataWritter,则需要在启动时更改注册。

如果我不知道要在启动时使用哪个IDataWritter实现,该怎么办。例如,我有由ClassA,ClassB和ClassC实现的IDataWritter接口,并且在运行时,我必须以某种方式解析这三个或三个中的一个?

1 个答案:

答案 0 :(得分:4)

这是一个很好的问题:)但这也是一个陷阱:)尽管如此,我还是会根据自己的经验提出这个陷阱并作出回答,并接受可能产生的强烈反对。

因此,在您的问题中,您描述了不同的情况,但是主要问题可能是“如果我不知道我想在启动时使用哪种实现,该怎么办”。以我的经验,设计良好的系统很少出现这种情况。

当我试图从总体上理解DI时,它在软件工程术语之外帮助了很多人。 DI基本上无非就是应用界面来帮助您的组件协同工作。同样适用于其他工程领域的原理。

让我们举个例子:如果您使用母板,它具有用于基本组成PC的各种组件的插槽:它具有用于CPU的插槽,用于图形卡的插槽等。然后您具有实际的CPU由Intel或AMD制造的并且与可插入的插槽兼容。您具有Nvidia或ATI制造的图形卡(它们仍然存在吗?:)),可以插入。这是相同的原理:主板可能是您应用程序中的一个具体类,套接字是实际的C#语言接口(您没有明确声明,我假设是C#),将它们注入到您的具体类中(例如,通过构造函数注入),然后您有了其他实现在启动时注册的接口(“套接字”)的类。

我解释了这个比喻来支持我的论点:如果您有要用于PC的主板,则必须在启动系统之前组装所有组件。 DI也是如此:可以随时更改组件不是DI的魔力。 DI中的魔力在于,如果您更改一个组件,则不应影响另一个组件。也就是说,如果您要插入其他图形卡,则不必重新构建整个主板(并可能需要重新构建整个主板)。

话虽这么说,实际上在某些情况下,您给出的示例不得不以某种方式欺骗系统(最常见的是基于插件的系统)。毕竟,如果将我的类推扩展到USB或HDMI,我们便拥有了即插即用的设备,不需要您先关机再进行更改。但是要分开头发,这些实际上并不是PC的依赖项,只是可选的额外外围设备,因此应以不同的方式对待它们。但是,为了避免麻烦,并再次确认在某些情况下需要这种动态特性,您还应该研究以下其他资源(请注意,这些是Autofac特定的实现,但是大多数DI容器具有类似的功能):

  • The enumeration implicit relationship type允许您在运行时解析注册到服务的所有组件。
  • Keyed service lookup允许您向注册添加密钥,并通过该密钥解析服务;即,您可以从“服务字典”中选择服务的组件。
  • Assembly scanning允许您仅指定一个程序集并从该程序集中获取给定服务的组件。这可能是解决组件最动态的方法。我已经在基于插件的系统中使用了它。