c# - Autofac - 解析在运行时实现相同接口(interface)的一个或多个类型

标签 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 接口(interface),在运行时,我必须以某种方式解析这 3 个或全部 3 个中的一个?

最佳答案

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

因此,在您的问题中,您描述了不同的场景,但主要问题可能是“如果我不知道在启动时要使用哪个实现怎么办”。根据我的经验,对于设计良好的系统来说,这种情况很少见。

当我尝试总体理解 DI 时,在软件工程术语之外思考它很有帮助。 DI 基本上无非就是应用接口(interface)来帮助你的组件协同工作;这一原则也适用于其他工程领域。

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

我解释了这个类比来支持我的论点:如果您有一 block 想要用于 PC 的主板,则必须在启动系统之前组装所有组件。 DI 也是如此:DI 的魔力并不在于您可以随时更改组件。 DI 的神奇之处在于,如果更改一个组件,则不会影响另一个组件。也就是说,如果您想插入不同的显卡,则不必重建整个主板(也可能包括其他组件)。

话虽这么说,确实在某些情况下,您给出的示例出现了,您必须以某种方式欺骗系统(最常见的是基于插件的系统)。毕竟,如果我的类比扩展到 USB 或 HDMI,我们拥有即插即用设备,不需要您关闭然后进行更改。但说实话,这些并不是 PC 的真正依赖项,只是可选的额外外围设备,因此应该以不同的方式对待它们。但为了不吹毛求疵,并再次承认在某些情况下需要这种动态特性,您应该研究以下一些其他资源(请注意,这些是特定于 Autofac 的实现,但大多数 DI 容器都具有类似的功能):

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

关于c# - Autofac - 解析在运行时实现相同接口(interface)的一个或多个类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54059880/

相关文章:

c# - Xamarin Forms 标签和条目在一行

c# - Autofac。如何在构造函数中注入(inject)一个开放的通用委托(delegate)

c# - Microsoft.office.interop.word.dll 可以在不安装 office 的情况下运行吗?

c# - session 超时后如何重定向到主页

ios - iOS 上的 ForceUpdateSize ListView 问题

autofac - 注册委托(delegate)时假定的 Autofac LifetimeScope 是什么?

c# - 使用 Autofac 进行属性注入(inject)的正确方法

c# - 如何获得收件箱文件夹和项目计数?

c# - Web 浏览器附加 header

xamarin - 如何更改 Xamarin.Forms 标签栏高度 (iOS)