dependency-injection - 对使用 IOC 容器、服务定位器和工厂感到困惑

标签 dependency-injection inversion-of-control ioc-container anti-patterns service-locator

假设我有一个 BaseForm这取决于 ILoggerIResourceManager或类似的东西。目前,它使用服务定位器解决了所需服务的正确实现,我知道这是一种反模式。

  • 使用构造函数注入(inject)是解决这种依赖关系的正确方法吗?
  • 我必须注册我的BaseForm吗? (及其'派生类型)在容器中,以便创建具有已解决依赖关系的实例?这不是把一切都复杂化了吗?
  • 使用包裹在服务定位器周围的静态工厂是不是很糟糕?
  • 抛开单元测试不谈,我真的会因为使用服务定位器反模式而受到惩罚吗?

  • 很抱歉一次问了很多问题。我已经阅读了以下 SO 问题和许多其他问题,但阅读它们只会增加我的困惑:
  • How to use Dependency Injection and not Service Locator
  • What's the difference between the Dependency Injection and Service Locator patterns?
  • How to avoid Service Locator Anti-Pattern?
  • 最佳答案

    如果可能的话,你应该总是使用依赖注入(inject),因为它有一些明显的优势。然而,对于 UI 技术,并不总是可以使用依赖注入(inject),因为某些 UI 技术(例如,在 .NET 空间中,Win Forms 和 Web Forms)只允许您的 UI 类(表单、页面、控件等)具有默认构造函数。在这种情况下,您将不得不退回到其他东西,即服务定位器。

    在这种情况下,我可以给你以下建议:

  • 仅针对无法由容器使用依赖注入(inject)创建的 UI 类以及无论如何都不是单元测试的东西回退到服务定位器。
  • 尝试在这些 UI 类中实现尽可能少的逻辑(如 Humble objects 仅与 View 相关的内容)。这允许您尽可能多地进行单元测试。
  • 将容器包裹在一个静态方法周围,以对应用程序的其余部分隐藏容器。确保在无法解决依赖关系时调用此静态方法失败。
  • 解析该类型的(默认)构造函数中的所有依赖项。这允许应用程序在创建该类型时无法解决其依赖项之一时快速失败,而不是稍后单击某个按钮时。
  • 在应用程序启动期间(或使用单元测试)检查是否可以创建所有这些 UI 类型。这使您不必通过整个应用程序(通过打开所有表单)来查看 DI 配置中是否存在错误。
  • 当容器无法构建类型时,没有理由在容器中注册它们。如果它们可以由容器创建(例如使用 ASP.NET MVC Controller 类),则显式注册它们会很有用,因为某些容器允许您预先验证配置,这将正确检测这些类型中的配置错误离开。

  • 除了单元测试之外,还有另外两个反对使用服务定位器的重要论据,这是 Mark Seemann 在他著名的博客文章 Service Locator is an Anti-Pattern 中给出的。 :
  • 服务定位器“隐藏类的依赖关系,导致运行时错误而不是编译时错误”
  • 服务定位器正在“使代码更难维护”
  • 关于dependency-injection - 对使用 IOC 容器、服务定位器和工厂感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11269293/

    相关文章:

    wpf - 从 ViewModel 触发 UIElement 的操作

    scala - 如何使 `CustomExecutionContext` 可用于 Play 2.6 Controller 中的依赖项注入(inject)?

    c# - 无法解析类型为“Microsoft.AspNetCore.Identity.IRoleStore”的服务

    java - 使用构造函数注入(inject)正确设计为可测试性而构建的类

    c# - 国际奥委会容器。注入(inject)容器

    c# - 简单的注入(inject)器为不同的命令使用不同的装饰器

    .net - 在多项目解决方案中使用 autofac

    c# - 为同一接口(interface)的多个实现设置属性

    c# - 如何配置结构图以提供具体类型的不同配置实例

    wcf - 如何告诉 MEF 重新创建对象?