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