.NET中的依賴注入實際上幫助我們解耦了我們的程式碼,是控制反轉和依賴反轉原則的具體實現。
.Net Core的依賴注入的好處:
1. application 更穩定,容易維護和演化;
2. 實現細節的變化,不需要到處更改,在宣告的時候進行替換即可;
3. 測試更容易,更好地mock依賴的service等。
4. 高階的模組或者服務不應該依賴於具體的實現,而是抽象。
服務的生命週期
1. Singleton: 應用程式執行期間是唯一的。需要考慮執行緒安全性,效率高
2. Scoped: 每個請求期間,例項唯一;需要考慮執行緒安全性,效率
3. Transient: 每次需要的時候例項化,不需要考慮執行緒安全,效率相對較低
關於服務的宣告週期: 一個服務不應該依賴於比它生命週期短的服務。
我們通過 AddTransient,AddSingleton, AddScoped 可以完成大多數的場景需要;
serviceDescriptor 物件一般是隱含在直接呼叫的AddSingleton/AddTransient/AddScoped中的。
var serviceDescriptor = new ServiceDescriptor.Singleton<IServiceA, ServiceA>(); services.Add(serviceDescriptor); === 等價於 services.AddSingleto<IServiceA, ServiceA>();
ServiceCollection 複雜場景的使用
1. 同一個介面的不同實現,TryAdd
DI container 會按照注入順序去resolve需要的介面實現,如下:
services.AddSingleton<IWeatherForecaster, WeatherForecaster>(); services.AddSingleton<IWeatherForecaster, AmazingWeatherForecaster>(); ------- public ServiceA(private IWeatherForecaster _weather) { }
_weather 例項化出來的 class 是typeof(AmazingWeatherForecaste), 按照我們在 ConfigureServices 中宣告的順序,最後一個起作用;
對ServiceCollection 的理解:serviceCollection是一個集合,裡面包含了webhost加入的一些內建 ServiceDescriptors, 以及我們在configureservices 中宣告的注入。
因此,本質上,我們對於這個servicecollection裡面的操作可以參照集合的操作。
2. 取代介面的實現和移除介面的所有實現
Replace: 取代servicetype 的第一個實現,示例如下。
services.AddSingleton<IWeatherForecaster, WeatherForecaster>();
services.Replace(ServiceDescriptor.Singleton<IWeatherForecaster, AmazingWeatherForecaster>());
通過如上程式碼,我們在 service collection中只能找到 IWeatherForecaster 實現 只有 AmazingWeatherForecaster, 因為AmazingWeatherForecaster 取代了 WeatherForecaster。
RemoveAll: 在service collection 中移除serviceType 的所有實現。
3. 註冊介面的多個實現
我們知道,在service collection中,是可以存在一個介面多個實現的註冊資訊的,那麼我們有什麼好的方法去註冊一個介面的多個實現麼? TryAddEnumerable
services.TryAddEnumerable(new[] { ServiceDescriptor.Singleton<ICourtBookingRule, ClubIsOpenRule>(), ServiceDescriptor.Singleton<ICourtBookingRule, MaxBookingLengthRule>(), ServiceDescriptor.Singleton<ICourtBookingRule, MaxPeakTimeBookingLengthRule>(), }); === 等價於 services.TryAddEnumerable(ServiceDescriptor.Singleton<ICourtBookingRule, ClubIsOpenRule>()); services.TryAddEnumerable(ServiceDescriptor.Singleton<ICourtBookingRule, MaxBookingLengthRule>());
4. 工廠模式
工廠模式允許我們在建立service 時候更加隨心所欲, 擁有自己的掌控度。
services.TryAddSingleton<EmailNotificationService>(); services.TryAddSingleton<SmsNotificationService>(); services.AddSingleton<INotificationService>(sp => new CompositeNotificationService( new INotificationService[] { sp.GetRequiredService<EmailNotificationService>(), sp.GetRequiredService<SmsNotificationService>() }));
例子中的使用場景是: 我們通過 CompositeNotificationService 去組合各種的 INotificationService, 因此使方不需要關心如何發notification 或者需要傳送多少型別的notification。
------------------------
鑑於後續內容還有不少,關於在DI 使用時的注意事項,及引入第三方的依賴注入框架,剩下內容會更新在下一篇。歡迎大家討論交流,指出不足,謝謝!