一. 依賴註入概述 在軟體設計的通用原則中,SOLID是非常流行的縮略語,它由5個設計原則的首字母構成:單一原則(S)、開放封閉原則(O)、里氏替換原則(L)、介面分離原則(I)、依賴反轉原則(D)。本篇介紹依賴反轉原則以及在ASP.NET Core中的實現。 直接依賴是指:當一個類需要另一個類協作 ...
一. 依賴註入概述
在軟體設計的通用原則中,SOLID是非常流行的縮略語,它由5個設計原則的首字母構成:單一原則(S)、開放封閉原則(O)、里氏替換原則(L)、介面分離原則(I)、依賴反轉原則(D)。本篇介紹依賴反轉原則以及在ASP.NET Core中的實現。
直接依賴是指:當一個類需要另一個類協作來完成工作的時候就產生了依賴。舉例比如:模塊 A 調用模塊 B 中的函數,而模塊 B 又調用模塊 C 中的函數,則編譯時 A 取決於 B,而 B 又取決於 C。這是有嚴重的依賴關係,不屬於鬆散耦合。
依賴反轉是指:高層模塊不應該依賴低層模塊,二者都應該依賴於抽象,是對介面而不是實現編程。當一個類(Class)需要被外部依賴,就需要把它抽象成一個介面(interface),如何把這個介面變成具體可調用的實例,就是由依賴註入來完成。依賴反轉是生成鬆散耦合應用程式的關鍵一環。當應用依賴反轉原則後,A 可以調用 B 實現的抽象上的方法,讓 A 可以在運行時調用 B,而 B 又在編譯時依賴於 A 控制的介面。 運行時程式執行的流程保持不變,但介面引入意味著可以輕鬆插入這些介面的不同實現。
假設一個方法從流讀取位元組,並把它們寫入某個緩衝:
//直接依賴 這裡的偽代碼依賴於兩個低層模塊,讀取器和寫入器。 void Copy() { Byte byte1; Reader reader = new Reader(); Writer writer = new Writer(); while (byte1 = reader.ReadFromStream()) writer.WriteTobuffer(byte1); }
//依賴反轉 這裡的偽代碼依賴於兩個抽象類,讀取器和寫入器。 void Copy(IReader reader, IWriter writer) { Byte byte1; while (byte1 = reader.ReadFromStream()) writer.WriteTobuffer(byte1) }
上面介面的讀取器和寫入器的實例誰來提供呢?需要使用依賴註入模式。實現依賴註入需要使用IoC 容器,目前有Unity和MEF 2 二種IoC 容器工具來實現。以及下麵講到ASP.NET Core自帶的依賴註入實現。
二. ASP.NET Core依賴註入
ASP.NET Core 支持依賴關係註入的設計模式,是類及其依賴關係之間實現控制反轉 (IoC)的技術。在ASP.NET Core中依賴註入解決的問題包括:
(1) 使用介面抽象化依賴關係實現。
(2) 註冊服務容器中的依賴關係。ASP.NET Core內置的服務容器 IServiceProvider。 實現在Startup.ConfigureServices 方法中註冊服務(服務一般是介面)。
(3) 將服務註入到使用它的類的構造函數中。
下麵示例中,使用具體類型 MyDependency 註冊 IMyDependency 服務, 註冊將服務生存期的範圍限定為單個請求的生存期。在MyDependency實現類中使用框架內部已註入好的ILogger來幫助列印日誌輸出。
// 第一步 使用介面抽象化來實現依賴反轉, 定義 IMyDependency 服務 public interface IMyDependency { Task WriteMessage(string message); } // IMyDependency 服務的實現類 public class MyDependency : IMyDependency { private readonly ILogger<MyDependency> _logger; public MyDependency(ILogger<MyDependency> logger) { _logger = logger; } public Task WriteMessage(string message) { _logger.LogInformation( "MyDependency.WriteMessage called. Message: {MESSAGE}", message); return Task.FromResult(0); } }
// 第二步在 將IMyDependency服務註冊到服務容器中。 public void ConfigureServices(IServiceCollection services) { //.... //每次請求時創建,貫穿整個請求 services.AddScoped<IMyDependency, MyDependency>(); //.... }
// 第三步 將服務註入到使用它的類的構造函數中,在Index.cshtml.cs類中調用IMyDependency服務的WriteMessage方法 public class IndexModel : PageModel { private readonly IMyDependency _myDependency; public IndexModel(IMyDependency myDependency) { this._myDependency = myDependency; } public void OnGet() { _myDependency.WriteMessage("IndexModel.OnGetAsync created this message."); } }
下麵是輸出WriteMessage方法的日誌信息:
參考文獻:
Microsoft.NET 企業級應用 架構設計
官方文檔:ASP.NET Core 依賴註入