1、簡介
DI:Dependency Injection,即依賴注入,他是IOC的具體實現。
在DI中,底層服務物件不再負責依賴關係的建立,而是交由頂端呼叫進行管理注入
好處:降低元件之間的耦合度,使程式碼更加靈活
2、例項
我們舉個例子,有個User Login的功能,Login需要透過DB驗證,DB需要讀取Config和進行Log記錄
依賴關係如圖
DI的概念,就是把DB的依賴(Config&Log)提到User層,該怎麼實現呢?
接著往下走...
3、程式碼結構
透過程式碼我們來看一下原理。
框架說明:
1)Service類庫:Standard2.1,類庫推薦都使用Standard,這樣可以在Framework、core、net之間通用
2)UserSite:Net5 控制檯程式
編碼內容:
ConfigService,包含兩種實現方式
namespace ConfigService { public interface IConfig { public string GetValue(string key);//獲取name的值 } } using System; namespace ConfigService { public class EnvironmentConfig : IConfig //從環境變數裡面讀取配置資訊,自行新增到電腦User裡面 { public string GetValue(string key) { return Environment.GetEnvironmentVariable(key, EnvironmentVariableTarget.User); } } } using System.IO; using System.Linq; namespace ConfigService { public class IniFileConfig : IConfig //從ini檔案讀取配置資訊,UserSite如果注入此服務,需要建立ini檔案 { string _filePath; public IniFileConfig(string filePath) { this._filePath = filePath; } public string GetValue(string key) { string str = ""; var kv = File.ReadAllLines(_filePath) .Select(x => x.Split("=")) .Select(x => new { key = x[0], value = x[1] }) .SingleOrDefault(x => x.key == key); return kv?.value; } } }
LogService,簡單實現
namespace LogService { public interface ILog { public void LogInfo(string msg); public void LogError(string msg); } } using System; namespace LogService { public class ConsoleLog : ILog { public void LogInfo(string msg) { Console.WriteLine($"Info:{msg}"); } public void LogError(string msg) { Console.WriteLine($"Error:{msg}"); } } }
DBService,只是做思路演示,這邊只要讀取到dblink就算訪問資料庫成功
namespace DBService { public interface IDBHelper { public bool CheckUser(string acc, string pwd); } } using LogService; using ConfigService; namespace DBService { public class SqlServerHelper : IDBHelper { private IConfig _config; private ILog _log; public SqlServerHelper(IConfig config,ILog log) //Net預設從建構函式進行以來注入 { this._config = config; this._log = log; } public bool CheckUser(string acc, string pwd) { var dblink = this._config.GetValue("dblink"); this._log.LogInfo($"獲取資料庫連結={dblink}"); if (string.IsNullOrWhiteSpace(dblink)) { this._log.LogError($"登入失敗"); return false; } this._log.LogInfo($"登入成功-{acc}-{pwd}"); return true; } } }
主題來了,UserSite Program程式碼如下:
我們需要注入SqlServerHelper服務,就需要將其依賴項一同注入,這樣就將具體實現類提到了頂端注入,從而進行解耦
比如:讀取配置檔案,我希望從哪讀取,就注入哪一個(注意,都注入的話,IConfig會以後注入的為準)
using System; using ConfigService; using LogService; using DBService; using Microsoft.Extensions.DependencyInjection; namespace UserSite { class Program { static void Main(string[] args) { ServiceCollection services = new ServiceCollection(); services.AddScoped<ILog, ConsoleLog>(); services.AddScoped<IConfig, EnvironmentConfig>(); //1、我希望從環境變數讀取配置 services.AddScoped(typeof(IConfig), x => new IniFileConfig("db.ini")); //2、我希望從ini讀取配置 services.AddScoped<IDBHelper, SqlServerHelper>(); using (var sp = services.BuildServiceProvider()) { var service = sp.GetRequiredService<IDBHelper>(); service.CheckUser("kxy", "123"); }; Console.ReadLine(); } } }
DI的簡單原理就是這樣。。