如何使用手动依赖注入实例化一个类?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用手动依赖注入实例化一个类?相关的知识,希望对你有一定的参考价值。

我有一个可能需要服务的类,以前通过依赖注入注册,具体取决于用户需求。

他通过静态方法GetInstance(bool)实现我的类,如果bool设置为true,那么我需要根据依赖注入调用构造函数。怎么做到这一点?

public class MyClass {
  private MyClass() {
    // ...
  }

  private MyClass(MyService env) {
    // ...
  }

  public static MyClass GetInstance(bool serviceIsNeeded) {
     if (serviceIsNeeded) {
         /* How to realize the following ?
          * if (!ServiceRegistered<MyService>())
          *     throw new ServiceNotFoundException(...);
          * return InstanciateWithDependencyInjection(typeof(MyClass));
         */
     }
     else
         return new MyClass();
  }
}

例如在Java中,你在构造函数的顶部放置一个@Inject标记,然后你就像这样实现你的类:MyClass myClass = getInjector(getContext()).getInstance(MyClass.class)

我在C#和ASP.NET Core 2中寻找相同的概念。

答案

Tl; Dr我认为你的方向是错误的。这几乎是Service Locator (anti) pattern


您应该尝试使用DI框架上下集成DI构建底层类,然后其他所有内容都接受依赖项。还有一个论点要说,“如果你注入一个类并且不使用它,为什么这很重要?”。提供该类没有构造开销(它不应该)只是注入并使用它。

所以你的课应该看起来像:

public class MyClass {

  //inject all the dependencies
  private MyClass(MyService env) {
    // ...
  }


}

很好,很简单。

服务定位器往往会导致组件过于紧密耦合。例如,在你的问题代码中,你如何对GetInstance进行单元测试?这很棘手,你不能注射嘲笑等。

DI的重点是将组件分离,以提高灵活性并简化单元测试。

我曾经有一个UnitTest项目,该项目引用了一个虚拟Web应用程序,用于注册所有必需的服务

看到这不是很好的测试,我会说你的测试会很快变得臃肿,难以维护。上面的地方很容易使用模拟引擎等进行测试。如果你改变x,你不希望它影响y的测试。

另一答案

我会保持MyClass清晰并将依赖放在构造函数中。如果构造函数无法解析此依赖项,则创建将手动创建对象的工厂类。像这样的东西:

public class MyClassFactory{

    public MyClass Create(){
        // insetead of manualy creating depenedecy service locator can be 
        // used
        return new MyClass(new MyService());
    }
}

public class MyClass{

    public MyClass(MyService myService){}
}

public class MyService {

}

以上是关于如何使用手动依赖注入实例化一个类?的主要内容,如果未能解决你的问题,请参考以下文章

依赖注入和控制反转

ThinkPHP6源码:从Http类的实例化看依赖注入是如何实现的

依赖注入:在无参数构造函数中实例化具体类时你会失去啥

为什么要用Spring的依赖注入

如何调用spring配置文件手动注入的bean

依赖注入