考慮到主題問題,在這裏不打算詳細講解依賴注入的概念,須要瞭解依賴注入的能夠關注個人DI&IoC分類講解,這裏咱們專一於ASP.NET Core 體系中系統自帶的原生IoC容器是如何讓咱們實現注入和解析的。html
在開始以前,咱們先了解一下服務的生命週期,這僅涉及到IServiceCollection和IServiceProvider兩個核心對象,這也是咱們開篇文章中闡述的兩個重要對象。app
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ITransientTest, TransientTest>(); services.AddSingleton<ISingletonTest, SingletonTest>(); services.AddScoped<IScopedTest, ScopedTest>(); ..... }
經過IServiceCollection這個對象,系統將相應的服務以不一樣的生命週期模式(Transient、Scoped和Singleton)註冊到ServiceCollection對象裏面。 ide
在此須要解釋一下服務的生命週期源碼分析
Singleton:整個應用程序生命週期內只建立一個實例 ui
Transient:每一次請求都會建立一個新的實例this
Scoped: 每次從同一個容器中獲取的實例是相同的、 spa
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註冊的服務類型提取相應的服務對象。code
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(); }
在這裏咱們再也不深究一個完整的流程的每一個階段,後面源碼分析的時候會結合整個流程展現。