为什么将IOC容器视为减少耦合的一种方式

本文关键字:方式 一种 耦合 IOC 为什么 | 更新日期: 2023-09-27 18:06:44

我正在考虑在我的项目中使用DI和Unity。我有一个问题:它将如何减少耦合?从我的角度来看,它正在增加耦合,因为:

  1. 我需要创建UnityContainer并在那里注册所有类型。这意味着我需要有对创建此容器的汇编中的所有程序集的引用。

    IUnityContainer UnityContainer;
    //....
    IUnityContainer UnityContainer= new UnityContainer();
    UnityContainer.RegisterType<IMyService, CustomerService>();
    
  2. 我需要使用Resolve创建我的服务实例,但这意味着我需要使用容器来引用汇编。

    var service = SomeClassWithContainer.UnityContainer.Resolve<IMyService>();
    

是我误解了什么,还是实际上是耦合的增加?

为什么将IOC容器视为减少耦合的一种方式

我想你误解了应该如何解决依赖关系。

1)。对Unity的引用应该只需要在你的引导代码中,它位于你的应用程序的单个中心位置。

2)。一旦引导完成,所有的依赖(理想情况下)都是使用构造函数注入来解决的,如果包含的类是通过Unity解决的,那么它是由Unity自动完成的——它是沿着对象图滴下的。您使用的示例实际上只是"服务定位器"模式,而不是DI。

这确实减少了耦合,因为不是直接创建你的类所依赖的具体类,而是"注入"依赖项(理想情况下是一些抽象,如接口)到你的类中,这允许你用其他类替代这些依赖项,即在单元测试场景中。

您的问题包含一个服务定位器反模式的示例:

public class UsesMyService
{
    private readonly IMyService _service;
    public UsesMyService()
    {
        _service = SomeClassWithContainer.UnityContainer.Resolve<IMyService>();
    }
}
由于信息流的方向不同,这与依赖注入模式有根本的不同:在上面的例子中,你伸出手,请求服务,而在下面的例子中,你是将服务交给:
public class UsesMyService
{
    private readonly IMyService _service;
    public UsesMyService(IMyService service)
    {
        _service = service;
    }
}

这种模式称为构造函数注入,将UsesMyService类与周围基础设施的细节解耦。现在,任何拥有IMyService实现的人都可以创建UsesMyService的实例,而不必知道如何配置中央静态位置。

他们怎么知道该配置什么?他们要么需要源代码,要么需要一些文档,告诉他们该类依赖于IMyService。构造函数参数在没有任何外部引用的情况下清晰地向消费者表达了这个需求。

如果你在你的库中遵循这个模式,你就承担了组装对象的责任,一直到最外层,称为组合根。这个位置(通常是顶级应用程序类)是唯一可以引用您正在使用的所有库的位置。是容器所在的位置,整个解决方案中没有其他类需要引用它。