关于c#:这是依赖注入吗?

Is this dependency injection?

本问题已经有最佳答案,请猛点这里访问。

如果我更改下面的代码,这是依赖注入吗

1
2
3
4
5
6
7
8
9
10
11
class Needer
{
    Needed obj;
    AnotherNeeded obj2;

    public Needer()
    {
        obj = new Neede();
        obj2 = new AnotherNeede();
    }
}

这个代码

1
2
3
4
5
6
7
8
9
10
11
class Needer
{
    Needed obj;
    AnotherNeeded obj2;

    public Needer(Needed param1, AnotherNeeded param2)
    {
        obj = param1;
        obj2 = param2;
    }
}


罗伯特·C·马丁在他的固体设计方案中描述了依赖注入。它基本上说明:

  • 高级模块不应依赖于低级模块。两者都应该依赖于抽象。

  • 抽象不应该依赖于细节。细节应该取决于抽象。

注意到在描述中有一个词被大量使用了吗?""抽象"。

在第二个示例中,问题的一部分是正确的,不再手动实例化类的实例,而是通过构造函数传递实例。但是,这会导致一个新的潜在问题,如果您需要某个类的不同实现(例如"模拟"和"真实"服务),该怎么办?如果您的构造函数采用抽象而不是具体的,那么您可以更改IOC配置中的实现。

任何类型的服务或功能类背后都应该有一个抽象。这使得您的代码更加灵活、可扩展和易于维护。因此,为了让您的第二个示例使用真正的依赖注入:

1
2
3
4
5
6
7
8
9
10
11
class Needer
{
    public INeeded obj { get; set; }
    public IAnotherNeeded obj2 { get; set; }

    public Needer(INeeded param1, IAnotherNeeded param2)
    {
        obj = param1;
        obj2 = param2;
    }
}

现在您可以拥有各种实现:

1
2
3
public class MockNeeded : INeeded

public class ApiNeeded : INeeded


第一个选项是通过在构造函数中更新依赖类来将其紧密耦合到依赖类。这使得孤立地测试该类非常困难(但并非不可能)。

第二个选项遵循有时被称为显式依赖性原则的内容。

The Explicit Dependencies Principle states:

Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.

也就是说,通常建议依赖类依赖于抽象,而不是具体化或实现关注点。

所以假设这些需要的类具有从中派生的接口/抽象

1
2
3
4
5
6
7
8
9
10
11
class Needer {
    private readonly INeeded obj;
    private readonly IAnotherNeeded obj2;

    public Needer(INeeded param1, IAnotherNeeded param2) {
        obj = param1;
        obj2 = param2;
    }

    //...
}

在将依赖类与实现关注点分离的过程中,允许对该类进行更大的灵活性,这使得在隔离中测试该类更容易。


第二个例子是DI(依赖注入)。DI通常与IOC(控制反转)一起使用。它负责根据一些配置为您创建依赖项。看看自动空调。AutoFac


注射本身不会发生。

相反,应该有某种工厂可以生成对象并使用依赖关系解析器(如果可用)。

例如,mvc.net框架就是那种"工厂",当它创建一个Controller类的实例时,它使用DependencyResolver.Current属性来填充构造函数参数。