DI 构造函数的模板化重构

Templated Refactoring of Constructors For DI

抱歉,如果这是 asked/answered 之前,我对这个主题的搜索让我找到了各种各样的主题,这些主题与我在这里的任务并没有直接关系。

我目前需要完成在内部代码库中重构大量构造函数以支持使用 Ninject 进行构造函数注入的目标。目前,我们有大量 KernelInstance.Get<T> 作为 getter 属性的实例,例如:

IRequiredService => StaticKernelReference.Get<IRequiredService>();

其中 StaticKernelReference 是对 Ninject StandardKernel 的静态实例的引用(我知道这也被认为是一种反模式,并且这种重构是杀死所有静态引用的目标的一部分到 Ninject 实例)

为了放弃这种显然被视为反模式的方法,我想重构这些参考方法:

public class ClassWithDependencies {
  readonly IRequiredSevice _requiredService;
  public ClassWithDependencies(IRequiredService requiredService){
    _requiredService = requiredService;
  }
}

我的问题实际上有两个方面,但如果能帮助解决任何一个问题,我们将不胜感激。

  1. 上面的示例是否提供了对这些依赖项进行构造函数注入的理想方法(我对 SO 和其他地方的研究表明是的,但如果我得出不正确的结论,我将不胜感激)。我非常有信心这种方法是对我们现有方法的改进,但如果这不理想,我宁愿不必对这个特定部分进行第二次重构。在大多数情况下,这些将不是可选的依赖项(以及我使用构造函数注入模式的原因),并且我知道用于 属性 注入的 [Inject] 装饰器。

  2. 我用 resharper 标记了这个问题,因为对于像这样的大规模重构,这是唯一想到的。有没有什么好的方法可以添加构造函数参数,然后代码 snippet/template 自动生成对构造函数中只读私有变量的赋值,并向 class 添加一个字段?虽然我可以手动执行此操作,但我预计这会非常乏味且耗时,因为至少有数百个这种模式的实例被使用。

  1. 是的,这种方法很好。向构造函数注入所需的依赖项使它们显式和可见。现在要弄清楚 class 的依赖关系,除了检查其源代码之外别无选择。当它们被注入构造函数时,情况就不再如此了。

  2. 要快速修复当前代码,您可以执行以下操作。你有这个代码行:

    IRequiredService SomeService => StaticKernelReference.Get<IRequiredService>();
    

    首先删除名称后面的所有内容:

    IRequiredService SomeService;
    

    这将使您的 属性 成为私人领域。然后 alt-enter 并使用 "Initialize field from constructor" 重构。然后你有这个:

    IRequiredService Service;
    public A(IRequiredService service) {
        Service = service;
    }
    

    然后继续 alt-enter "Rename to _service"(取决于您如何命名您的私有字段),然后再次 alt-enter 和 "make field readonly".

    readonly IRequiredService _service;
    public A(IRequiredService service) {
        _service = service;
    }