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

时间:2011-08-27 20:01:25

标签: c# .net dependency-injection unity-container

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

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

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

    var service = SomeClassWithContainer.UnityContainer.Resolve<IMyService>();
    
  3. 我是否误解了某些事情,或者实际上是在增加耦合?

2 个答案:

答案 0 :(得分:9)

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

1。)只有在您的应用程序中单个中心位置的引导代码中才需要引用Unity。

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

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

答案 1 :(得分:6)

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

public class UsesMyService
{
    private readonly IMyService _service;

    public UsesMyService()
    {
        _service = SomeClassWithContainer.UnityContainer.Resolve<IMyService>();
    }
}

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

public class UsesMyService
{
    private readonly IMyService _service;

    public UsesMyService(IMyService service)
    {
        _service = service;
    }
}

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

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

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