为什么使用依赖注入和控制反转

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

依赖注入(Dependency Injection,简称DI)则是一种实现控制反转的方法。

理解了依赖注入,就理解了控制反转

依赖注入

依赖项是指一个对象所依赖的对象。

public class IndexController : Controller
{
    private readonly Dependency _dependency = new Dependency();

    public IActionResult Index()
    {
        _dependency.WriteMessage("message");
        return null;
    }
}

public class Dependency
{
    public void WriteMessage(string message)
    {
        Console.WriteLine(message);
    }
}

在以上代码中,在类IndexController中直接实例化了Dependency对象,并调用其WriteMessage方法。

那么Dependency就是IndexController的依赖项。这样的直接依赖会产生问题,应避免使用,原因如下:

  • 要用不同的实现替换 Dependency,必须修改 IndexController 类。
  • 如果 Dependency 具有依赖项,则必须由 IndexController 类对其进行配置。 在具有多个依赖于 Dependency 的类的大型项目中,配置代码将分散在整个应用中。
  • 这种实现很难进行单元测试。 应用需使用模拟 Dependency 类,而这种方法很难实现。

依赖注入通过以下方式解决这些问题:

  • 使用接口或基类将依赖关系抽象化。
  • 在服务容器中注册依赖关系。 ASP.NET Core 提供了一个内置的服务容器 IServiceProvider。 服务通常已在应用的 Startup.ConfigureServices 方法中注册。
  • 将服务注入到使用它的类的构造函数中。 服务容器负责创建依赖关系的实例,并在不再需要时将其释放。

Dependency类抽象成接口IDependency

public interface IDependency
{
    void WriteMessage(string message);
}

Dependency实现接口IDependency

public class Dependency : IDependency
{
    public void WriteMessage(string message)
    {
        Console.WriteLine(message);
    }
}

通过Startup类的ConfigureServices方法,在服务容器中注册具体类型 为DependencyIMyDependency 服务。AddScoped表示使用范围内生命周期注册服务。

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IDependency, Dependency>();
    services.AddControllersWithViews();
}

IndexController中注入IDependency服务并调用WriteMessage方法

public class IndexController : Controller
{
    private readonly IDependency _dependency;

    public IndexController(IDependency dependency)
    {
        this._dependency = dependency;
    }

    public IActionResult Index()
    {
        _dependency.WriteMessage("message");
        return null;
    }
}

通过使用依赖注入模式,类IndexController:

  • 不再使用具体类型 Dependency,仅使用它实现的 IDependency 接口。 这样可以轻松地更改IDependency的实现,而无需修改类IndexController
  • 不直接创建 Dependency 的实例,而是由服务容器创建。

控制反转

那么到底什么被反转了?获得依赖对象的过程被反转了。

在以上的例子中,IndexController获得Dependency对象的过程被反转了。以往是IndexController直接实例化Dependency对象,现在是由服务容器实例化,并通过IndexController的构造函数注入。

ASP.NET Core依赖注入

在我之前的文章中有详细介绍

参考

ASP.NET Core 依赖注入

控制反转

上一篇:python的dir、help、str用法


下一篇:c#-无法同时保存修改后的实体和新实体