05 | 依賴注入:良好架構的起點
注冊完畢之后,想替換某些組件的某些部分時,可以使用 Replace 和 RemoveAll
services.AddSingleton<IOrderService>(new OrderService());
services.Replace(ServiceDescriptor.Singleton<IOrderService, OrderServiceEx>());// 替換掉注冊的第一個實現
啟動程序,輸出如下:
獲取到服務實例:DependencyInjectionDemo.Services.OrderServiceEx:25560520
從結果看出,注冊的 OrderService 被替換為 OrderServiceEx
下面介紹 RemoveAll
services.AddSingleton<IOrderService>(new OrderService());
services.AddSingleton<IOrderService, OrderServiceEx>();
services.RemoveAll<IOrderService>();// 移除所有 IOrderService 的注冊
這種情況下程序會報錯,因為所有 IOrderService 的注冊被移除
Unable to resolve service for type 'DependencyInjectionDemo.Services.IOrderService'
下面介紹如何注冊泛型模板
當需要注冊一組泛型實現的時候
實際上注冊的時候並不知道泛型類的具體類型入參
依賴注入框架為我們提供了泛型模板的注冊方式
通過一行代碼來注冊所有此泛型的具體實現
定義一個泛型接口
namespace DependencyInjectionDemo.Services
{
public interface IGenericService<T>
{
}
public class GenericService<T> : IGenericService<T>
{
public T Data { get; private set; }
public GenericService(T data)
{
this.Data = data;
}
}
}
泛型模板注冊方法
services.AddSingleton(typeof(IGenericService<>), typeof(GenericService<>));
它的生命周期與之前的注冊方式是一致的
不過它無法通過泛型 API 注冊
需要注冊兩個 service 的 type
第一個入參是服務的類型
第二個入參是服務實現的類型
接下來,看看如何在 controller 中使用
// 在構造函數中添加兩個入參,IOrderService 和 IGenericService
// 通過斷點調試查看 genericService 的類型可得知,泛型的具體實現可以用容器里面的任意類型來替代
public WeatherForecastController(ILogger<WeatherForecastController> logger, IOrderService orderService, IGenericService<IOrderService> genericService)
{
_orderService = orderService;
_logger = logger;
}
在 controller 中有兩種依賴注入的實例的獲取方式:
- 通過 controller 構造函數注入
- 通過 [FromServices] 注入
當定義一個 controller 的時候
它的服務是大部分接口都需要使用的情況下
推薦的做法是用構造函數注入的方式
如果這個服務僅僅在某一個接口使用的情況下
推薦使用 [FromServices] 注入
GitHub源碼鏈接:
https://github.com/witskeeper/geektime/tree/master/samples/DependencyInjectionDemo
本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。
歡迎轉載、使用、重新發布,但務必保留文章署名 鄭子銘 (包含鏈接: http://www.cnblogs.com/MingsonZheng/ ),不得用於商業目的,基於本文修改后的作品務必以相同的許可發布。
如有任何疑問,請與我聯系 (MingsonZheng@outlook.com) 。