本文章介绍 ASP.NET Core 内置的依赖注入生命周期及其不同的注册方式
先决条件
.NET 8 SDK
介绍
依赖关系注入 (DI) 软件设计模式,这是一种在类及其依赖项之间实现控制反转(Ioc)的技术,这有助于减少组件之间的直接依赖,使得代码更加模块化
依赖注入组件
ASP.NET Core 内置的依赖注入组件使用了接口分离模式
抽象包只包含接口的定义,实现包则包含具体的实现,使用时通过注入具体实现即可,未来可以做任意扩展
核心类型
IServiceCollection 负责服务的注册
ServiceDescriptor 每一个服务注册时的信息
IServiceProvider 是具体的容器,由 ServiceCollection Build 创建
IServiceScope 表示一个容器的子容器的生命周期
生命周期和注册
单例 Singleton
作用域 Scoped
瞬时 Transient
注册服务不同生命周期的服务
// 单例
services.AddSingleton<IT, T>();
// 作用域
services.AddScoped<IT, T>();
// 瞬时
services.AddTransient<IT, T>();
复制代码
花式注册
// 直接注入实例
services.AddSingleton<IT>(new T());
// 工厂方式注册(适用于单例、范围、瞬时)
services.AddSingleton<IT>(provider => {
// provider 可从容器内获取更多对象,进行组装
return new T();
});
复制代码
尝试注册
尝试注册表示如果服务已经注册过了,就不再注册
// 服务已经注册过了,就不再注册
services.TryAddSingleton<IT, T>();
// 相同类型的服务接口,实现是不同的就可以注册进去
// 如果实现类是相同的,就不注册进去
services.TryAddEnumerable(ServiceDescriptor.Singleton<IT, T>());
//services.TryAddEnumerable(ServiceDescriptor.Singleton<IT>(p =>
//{
// return new T();
//}));
复制代码
移动和替换注册
// Replace 会替换掉我们注册的第一个实现(基于IT替换)
services.Replace(ServiceDescriptor.Singleton<IT, T>());
// 移除所有基于 IT 注册
services.RemoveAll<IT>();
复制代码
注册泛型模板
public interface IService<T> { ... }
public class Service<T> : IService<T> { ... }
// 注册泛型模板
services.AddSingleton(typeof(IService<>), typeof(Service<>));
复制代码
实例获取方法
使用构造函数注入
大部分接口都需要使用情况下使用构造函数注入
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
public void Get()
{
_logger.LogInformation($"日志");
}
}
复制代码
将服务直接注入到操作方法
仅仅在某一个接口使用情况下使用 FromServices 注入
[HttpGet]
public void Get([FromServices] ILogger<WeatherForecastController> logger)
{
logger.LogInformation($"日志");
}
复制代码
参考文档
依赖注入:良好架构的起点 - 肖伟宇
评论