1. 程式人生 > 實用技巧 >為什麼使用依賴注入和控制反轉

為什麼使用依賴注入和控制反轉

控制反轉(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 依賴注入

控制反轉