Alva

Alva

programmer
github
telegram
email

dotnet 中的依赖注入-01.介绍

本文示例代碼,均採用 .NET 6,具體的代碼可以在這個倉庫 Articles.DI 中獲取。

讓我們看這麼一段簡單的代碼:

// https://github.com/alva-lin/Articles.DI/tree/master/WorkerService1
public class MessageWriter {
	public void Write(string message) => Console.WriteLine(message);
}

public class Worker : BackgroundService {
	private readonly MessageWriter _msgWriter = new MessageWriter();

	protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
		while (!stoppingToken.IsCancellationRequested) {
			_msgWriter.Write($"Worker running at: {DateTime.Now}");
			await Task.Delay(1000, stoppingToken);
		}
	}
}

在上面的代碼中,Worker類包含有一個MessageWriter類的實例成員,這個類創建並直接依賴於MessageWriter類。這樣的代碼有一些問題:

  • 如果_msgWriter變量要替換成別種類型的實現,需要修改Worker類;
  • 如果MessageWriter類具有其他依賴項,則必須在Worker類中進行配置;
  • 難以對Worker類進行單元測試。

如果有一個統一的管理者,負責MessageWriter類型的實例化,然後將其傳遞給有需求的類,就能做到這兩個類之間的依賴解除,減少了硬編碼。而這,就是依賴注入。

依賴注入和控制反轉#

依賴注入(英文 Dependency Injection,簡稱 DI),是一種在類及其依賴項之間實現控制反轉(英文 Inversion of Control,簡稱 IoC)的技術。

控制反轉,是面向對象編程中的一種設計原則,可以用來減少程序代碼間的耦合程度。除了依賴注入外,還有一種實現控制反轉的方法,叫做 “依賴查找”。

大多數程序都由多個類相互引用,彼此依賴合作以實現業務邏輯,這使得每個對象都需要獲取其他服務的引用。如果這個獲取過程需要靠對象自己實現,那麼這將導致類之間高度耦合,難以維護和調試。

傳統應用中,如果 A 服務要獲取 B 服務,則需要在自己的代碼塊中實例化。而如果使用依賴注入,A 服務只需聲明所需的服務,由外部容器來負責生成實例,A 服務只需接收即可。整個過程從主動變成了被動,反轉了對象的獲取過程,即實現了控制反轉

下面兩張圖展示了兩種依賴項關係圖:

直接依賴項關係圖

直接依賴項關係:類 A 調用類 B 的方法,類 B 調用類 C 的方法,則在編譯時,類 A 依賴於類 B,類 B 依賴於類 C。

反轉依賴項關係圖

應用依賴反轉後,類 A 引用的是接口 IB 的方法,不再直接依賴於類 B。在編譯時,則是類 A 和類 B 引用了接口 IB,和前面的直接依賴相比,反轉了依賴項。而類 B 和類 C 之間也是相似的。

IoC 解耦過程

這張圖,生動形象的解釋了控制反轉是如何解耦服務之間的依賴。

參考鏈接#

依賴注入 - 維基百科

控制反轉 - 維基百科

依賴關係反轉 - 現代 ASP.NET Web 應用程序電子書

.NET 中的依賴關係注入

Inversion of Control Containers and the Dependency Injection pattern

依賴注入和控制反轉的理解

控制反轉(IoC)與依賴注入(DI)

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。