Dependency injection DI容器的好处和正确使用

Dependency injection DI容器的好处和正确使用,dependency-injection,inversion-of-control,ioc-container,Dependency Injection,Inversion Of Control,Ioc Container,我很难获得像Ninject、Unity之类的IoC(DI)容器的优势。我理解的概念如下: DI:向需要依赖项的类中注入依赖项(最好通过构造函数注入)。我完全明白为什么不那么紧密的耦合是一件好事 public MyClass{ ISomeService svc; public MyClass(ISomeService svc){ svc = svc; } public doSomething(){ svc.doSomethi

我很难获得像Ninject、Unity之类的IoC(DI)容器的优势。我理解的概念如下:

  • DI:向需要依赖项的类中注入依赖项(最好通过构造函数注入)。我完全明白为什么不那么紧密的耦合是一件好事

    public MyClass{
        ISomeService svc;  
    
        public MyClass(ISomeService svc){
            svc = svc;
        }
    
        public doSomething(){
            svc.doSomething();
        }
    }
    
  • 服务定位器:当在需要依赖性的类中直接使用“容器”时,用于解决依赖性。我确实明白这会产生另一种依赖性,我也看到基本上没有任何东西被注射

    public MyClass{                 
        public MyClass(){}
    
        public doSomething(){
            ServiceLocator.resolve<ISomeService>().doSomething();
        }
    }
    
    公共MyClass{
    公共MyClass(){}
    公共剂量测定法(){
    ServiceLocator.resolve().doSomething();
    }
    }
    
现在,让我困惑的是“DI容器”的概念。对我来说,它看起来就像一个服务定位器——据我所知——应该只在应用程序的入口点/启动方法中使用它来注册和解析依赖性,并将它们注入到其他类的构造函数中——而不是在需要依赖性的具体类中(可能与服务定位器被视为“坏”的原因相同)

  • 当我可以创建依赖性并将其传递给构造函数时,使用容器的目的是什么

    public void main(){                 
        DIContainer.register<ISomeService>(new SomeService());
        // ...
    
        var myclass = new MyClass(DIContainer.resolve<ISomeService>());
        myclass.doSomething();
    }
    
    public void main(){
    register(newsomeservice());
    // ...
    var myclass=newmyclass(DIContainer.resolve());
    myclass.doSomething();
    }
    
  • 将所有依赖项传递给应用程序初始化方法中的所有类真的有意义吗?可能最终需要(或不需要)100个依赖项,仅仅因为这被认为是在init方法中创建它们的良好实践

当我可以创建依赖性并将其传递给构造函数时,使用容器的目的是什么

public void main(){                 
    DIContainer.register<ISomeService>(new SomeService());
    // ...

    var myclass = new MyClass(DIContainer.resolve<ISomeService>());
    myclass.doSomething();
}
DI容器应该可以帮助您快速创建对象图。您只需告诉它您想要为哪些抽象使用哪些具体实现(注册阶段),然后它就可以创建您想要的任何对象(解析阶段)

如果您创建依赖项并将它们传递给构造函数(在应用程序初始化代码中),那么您实际上正在这样做

我认为在很多情况下,纯DI是一种更好的方法

将所有依赖项传递给应用程序初始化方法中的所有类真的有意义吗?可能最终需要(或不需要)100个依赖项,仅仅因为这被认为是在init方法中创建它们的良好实践

我会说是的。你应该在应用程序启动时创建对象图。这叫做

如果您需要在应用程序启动后创建对象,那么您应该使用(主要是抽象工厂)。这样的工厂将与组合根中的其他对象一起创建

您的类不应该在构造函数中做太多工作,这将降低在组合根创建所有依赖项的成本


但是,我想说,在特殊情况下,可以使用new关键字创建某些类型的对象。例如,当对象是一个简单的对象时

下面是一篇关于使用容器的优缺点的好文章: