原文:
考虑到主题问题,在这里不打算详细讲解依赖注入的概念,需要了解依赖注入的可以关注我的DI&IoC分类讲解,这里我们专注于ASP.NET Core 体系中系统自带的原生IoC容器是如何让我们实现注入和解析的。
服务的生命周期
在开始之前,我们先了解一下服务的生命周期,这仅涉及到IServiceCollection和IServiceProvider两个核心对象,这也是我们开篇文章中阐述的两个重要对象。
服务注册:
public void ConfigureServices(IServiceCollection services) { services.AddTransient(); services.AddSingleton (); services.AddScoped (); ..... }
通过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(); services = services.AddScoped (); services = services.AddSingleton (); IServiceProvider serviceProvider = services.BuildServiceProvider(); Console.WriteLine(ReferenceEquals(serviceProvider.GetService (), serviceProvider.GetService ())); Console.WriteLine(ReferenceEquals(serviceProvider.GetService (), serviceProvider.GetService ())); Console.WriteLine(ReferenceEquals(serviceProvider.GetService (), serviceProvider.GetService ())); IServiceProvider serviceProvider1 = serviceProvider.CreateScope().ServiceProvider; IServiceProvider serviceProvider2 = serviceProvider.CreateScope().ServiceProvider; Console.WriteLine(ReferenceEquals(serviceProvider1.GetService (), serviceProvider1.GetService ())); Console.WriteLine(ReferenceEquals(serviceProvider1.GetService (), serviceProvider2.GetService ())); Console.WriteLine(ReferenceEquals(serviceProvider1.GetService (), serviceProvider2.GetService ())); /* False * True * True * True * False * True */ }}
对象解析:
当我们需要从容器中解析一个对象出来的时候,用到了IServiceProvider对象,它根据IServiceCollection注册的服务类型提取相应的服务对象。
public TestController(IServiceProvider serviceProvider){ //如果没有,则返回null var testService1 = serviceProvider.GetService(); //如果没有,则抛出InvalidOperationException异常 var testService2 = serviceProvider.GetRequiredService (); //获取对应的集合 var testService3 = serviceProvider.GetServices (); var testService4 = serviceProvider.GetRequiredServices ();}
追本溯源
这是WebHost调用Startup类的Configure方法创建管道的过程
public void Initialize(){ _startup = _hostingServiceProvider.GetService(); _applicationServices = _startup.ConfigureServices(_applicationServiceCollection); EnsureServer(); var builderFactory = _applicationServices.GetRequiredService (); var builder = builderFactory.CreateBuilder(Server.Features); builder.ApplicationServices = _applicationServices; var startupFilters = _applicationServices.GetService >(); Action configure = _startup.Configure; foreach (var filter in startupFilters.Reverse()) { configure = filter.Configure(configure); } configure(builder); this._application = builder.Build(); }
在这里我们不再深究一个完整的流程的每个阶段,后面源码分析的时候会结合整个流程展示。
posted on 2019-04-24 14:13 阅读( ...) 评论( ...)