为什么IOC容器被认为是减少耦合的一种方法?

Ole*_*nyk 1 .net c# dependency-injection unity-container

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

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

    IUnityContainer UnityContainer;
    //....
    IUnityContainer UnityContainer= new UnityContainer();
    UnityContainer.RegisterType<IMyService, CustomerService>();
    
    Run Code Online (Sandbox Code Playgroud)
  2. 我需要使用Resolve创建我的服务实例,但这意味着我需要对容器的程序集进行引用.

    var service = SomeClassWithContainer.UnityContainer.Resolve<IMyService>();
    
    Run Code Online (Sandbox Code Playgroud)

我误解了某些东西,或者实际上它是否正在增加耦合?

Bro*_*ass 9

我认为你误解了你的依赖关系应该如何解决.

1.)只应在您的应用程序中的单个中心位置的引导代码中引用Unity .

2.)一旦完成引导,所有依赖关系(理想情况下)都是使用构造函数注入来解析的,如果通过Unity解析包含类,Unity会自动完成它 - 它正在逐渐减少对象图.您使用的示例实际上只是"服务定位器"模式而不是DI.

这确实减少了耦合,因为不是直接创建类所依赖的具体类,而是将"依赖"(再次理想地是一些抽象,如接口)"注入"到类中,这允许您将这些依赖项替换为其他类,即在单元测试场景中.

  • 这是正确的:自举组件(组合根)需要引用所有其他组件才能进行连线.通过让应用程序的这一部分依赖于所有其他程序集,您可以减少应用程序的所有其他部分彼此之间的耦合量,这远远超过了在该单个位置具有该复杂性的成本. (3认同)

Bry*_*tts 6

您的问题包含Service Locator反模式的示例:

public class UsesMyService
{
    private readonly IMyService _service;

    public UsesMyService()
    {
        _service = SomeClassWithContainer.UnityContainer.Resolve<IMyService>();
    }
}
Run Code Online (Sandbox Code Playgroud)

由于信息流的方向,这与依赖注入模式根本不同:在上面的示例中,您伸出并询问服务,而在下面的示例中,您获得服务:

public class UsesMyService
{
    private readonly IMyService _service;

    public UsesMyService(IMyService service)
    {
        _service = service;
    }
}
Run Code Online (Sandbox Code Playgroud)

这种模式称为构造函数注入,它将UsesMyService类与周围基础结构的细节分离.现在,任何具有实现的人都IMyService可以创建实例而UsesMyService无需知道配置中央静态位置.

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

如果您在整个库中遵循此模式,那么您将负责将对象组装到最外层(称为组合根).这个单一位置(通常是顶级应用程序类)是唯一一个引用您正在使用的所有库的位置.就是容器所在的位置,整个解决方案中没有其他类需要引用它.