ASP.NET Core - 依赖注入
考虑到主题问题,在这里不打算详细讲解依赖注入的概念,需要了解依赖注入的可以关注我的DI&IoC分类讲解,这里我们专注于ASP.NET Core 体系中系统自带的原生IoC容器是如何让我们实现注入和解析的。
服务的生命周期
在开始之前,我们先了解一下服务的生命周期,这仅涉及到IServiceCollection和IServiceProvider两个核心对象,这也是我们开篇文章中阐述的两个重要对象。
服务注册:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ITransientTest, TransientTest>();
services.AddSingleton<ISingletonTest, SingletonTest>();
services.AddScoped<IScopedTest, ScopedTest>();
.....
}
通过IServiceCollection这个对象,系统将相应的服务以不同的生命周期模式(Transient、Scoped和Singleton)注册到ServiceCollection对象里面。
在此需要解释一下服务的生命周期
Singleton:整个应用程序生命周期内只创建一个实例
Transient:每一次请求都会创建一个新的实例
Scoped: 每次从同一个容器中获取的实例是相同的、
interface ITransientTest { } interface ISingletonTest { } interface IScopedTest { } class TransientTest : ITransientTest { } class SingletonTest : ISingletonTest { } class ScopedTest : IScopedTest { } class Program { static void Main(string[] args) { IServiceCollection services = new ServiceCollection(); services = services.AddTransient<ITransientTest, TransientTest>(); services = services.AddScoped<IScopedTest, ScopedTest>(); services = services.AddSingleton<ISingletonTest, SingletonTest>(); IServiceProvider serviceProvider = services.BuildServiceProvider(); Console.WriteLine(ReferenceEquals(serviceProvider.GetService<ITransientTest>(), serviceProvider.GetService<ITransientTest>())); Console.WriteLine(ReferenceEquals(serviceProvider.GetService<IScopedTest>(), serviceProvider.GetService<IScopedTest>())); Console.WriteLine(ReferenceEquals(serviceProvider.GetService<ISingletonTest>(), serviceProvider.GetService<ISingletonTest>())); IServiceProvider serviceProvider1 = serviceProvider.CreateScope().ServiceProvider; IServiceProvider serviceProvider2 = serviceProvider.CreateScope().ServiceProvider; Console.WriteLine(ReferenceEquals(serviceProvider1.GetService<IScopedTest>(), serviceProvider1.GetService<IScopedTest>())); Console.WriteLine(ReferenceEquals(serviceProvider1.GetService<IScopedTest>(), serviceProvider2.GetService<IScopedTest>())); Console.WriteLine(ReferenceEquals(serviceProvider1.GetService<ISingletonTest>(), serviceProvider2.GetService<ISingletonTest>())); /* False * True * True * True * False * True */ } }
对象解析:
当我们需要从容器中解析一个对象出来的时候,用到了IServiceProvider对象,它根据IServiceCollection注册的服务类型提取相应的服务对象。
public class Test { private readonly IServiceProvider _serviceProvider;
public Test(IServicCollection serviceCollection) { _serviceProvider = serviceCollection.BuildServiceProvider(); } public TestController() { //如果没有,则返回null var testService1 = _serviceProvider.GetService<ITestService>(); //如果没有,则抛出InvalidOperationException异常 var testService2 = _serviceProvider.GetRequiredService<ITestService>(); //获取对应的集合 var testService3 = _serviceProvider.GetServices<ITestService>(); var testService4 = _serviceProvider.GetRequiredServices<ITestService>(); } }
追本溯源
这是WebHost调用Startup类的Configure方法创建管道的过程
public void Initialize() { _startup = _hostingServiceProvider.GetService<IStartup>(); _applicationServices = _startup.ConfigureServices(_applicationServiceCollection); EnsureServer(); var builderFactory = _applicationServices.GetRequiredService<IApplicationBuilderFactory>(); var builder = builderFactory.CreateBuilder(Server.Features); builder.ApplicationServices = _applicationServices; var startupFilters = _applicationServices.GetService<IEnumerable<IStartupFilter>>(); Action<IApplicationBuilder> configure = _startup.Configure; foreach (var filter in startupFilters.Reverse()) { configure = filter.Configure(configure); } configure(builder); this._application = builder.Build(); }
在这里我们不再深究一个完整的流程的每个阶段,后面源码分析的时候会结合整个流程展示。
如果你觉得该文章还不错且有所收获,请右下角推荐一下,也可留下您的问题或建议,让我们共同进步。
原创博客请在转载时保留原文链接或者在文章开头加上本人博客地址!
作者:lex-wu,原文链接:https://www.cnblogs.com/lex-wu/p/10739517.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?