一、.Net Core 依賴注入詳解及Autofac使用

懶懶的佩奇發表於2021-07-06

.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 使用時的注意事項,及引入第三方的依賴注入框架,剩下內容會更新在下一篇。歡迎大家討論交流,指出不足,謝謝!

相關文章