本文章介绍 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($"日志"); }
复制代码
参考文档
依赖注入:良好架构的起点 - 肖伟宇
评论