前一篇提到 webHost.CreateDefaultBuilder(args) 方法创建了 WebHostBuilder 实例, WebHostBuilder 实例有三个主要功能 1, 构建了 IConfiguration 实例和基础环境配置, 2, 构建了 IServiceCollection 服务, 也就是依赖注入的容器, 3, 创建了 webhost 实例, 这个 webhost 就是我们的接收请求的第一个管道, 其中暴露出来的主要方法 Build, 请看源代码:
- public IWebHost Build()
- {
- if (!_webHostBuilt)
- {
- _webHostBuilt = true;
- AggregateException hostingStartupErrors;
- IServiceCollection serviceCollection = BuildCommonServices(out hostingStartupErrors);
- IServiceCollection serviceCollection2 = serviceCollection.Clone();
- IServiceProvider hostingServiceProvider = _003CBuild_003Eg__GetProviderFromFactory_007C13_0(serviceCollection);
- if (!_options.SuppressStatusMessages)
- {
- if (Environment.GetEnvironmentVariable("Hosting:Environment") != null)
- {
- Console.WriteLine("The environment variable'Hosting:Environment'is obsolete and has been replaced with'ASPNETCORE_ENVIRONMENT'");
- }
- if (Environment.GetEnvironmentVariable("ASPNET_ENV") != null)
- {
- Console.WriteLine("The environment variable'ASPNET_ENV'is obsolete and has been replaced with'ASPNETCORE_ENVIRONMENT'");
- }
- if (Environment.GetEnvironmentVariable("ASPNETCORE_SERVER.URLS") != null)
- {
- Console.WriteLine("The environment variable'ASPNETCORE_SERVER.URLS'is obsolete and has been replaced with'ASPNETCORE_URLS'");
- }
- }
- AddApplicationServices(serviceCollection2, hostingServiceProvider);
- WebHost webHost = new WebHost(serviceCollection2, hostingServiceProvider, _options, _config, hostingStartupErrors);
- try
- {
- webHost.Initialize();
- ILogger<WebHost> requiredService = webHost.Services.GetRequiredService<ILogger<WebHost>>();
- foreach (IGrouping<string, string> item in from g in _options.GetFinalHostingStartupAssemblies().GroupBy((string a) => a, StringComparer.OrdinalIgnoreCase)
- where g.Count()> 1
- select g)
- {
- requiredService.LogWarning($"The assembly {item} was specified multiple times. Hosting startup assemblies should only be specified once.");
- }
- return webHost;
- }
- catch
- {
- webHost.Dispose();
- throw;
- }
- }
- throw new InvalidOperationException(Resources.WebHostBuilder_SingleInstance);
- }
- View Code
这个方法中有几个笔记重要的部分, 下面我给标记一下
调用 BuildCommonServices 私有方法主要是注入一些程序所需的基础组件, 请看源代码:
- private IServiceCollection BuildCommonServices(out AggregateException hostingStartupErrors)
- {
- hostingStartupErrors = null;
- _options = new WebHostOptions(_config, Assembly.GetEntryAssembly()?.GetName().Name);
- if (!_options.PreventHostingStartup)
- {
- List<Exception> list = new List<Exception>();
- foreach (string item in _options.GetFinalHostingStartupAssemblies().Distinct(StringComparer.OrdinalIgnoreCase))
- {
- try
- {
- foreach (HostingStartupAttribute customAttribute in Assembly.Load(new AssemblyName(item)).GetCustomAttributes<HostingStartupAttribute>())
- {
- ((IHostingStartup)Activator.CreateInstance(customAttribute.HostingStartupType)).Configure(this);
- }
- }
- catch (Exception innerException)
- {
- list.Add(new InvalidOperationException("Startup assembly" + item + "failed to execute. See the inner exception for more details.", innerException));
- }
- }
- if (list.Count> 0)
- {
- hostingStartupErrors = new AggregateException(list);
- }
- }
- string contentRootPath = ResolveContentRootPath(_options.ContentRootPath, AppContext.BaseDirectory);
- _hostingEnvironment.Initialize(contentRootPath, _options);
- _context.HostingEnvironment = _hostingEnvironment;
- ServiceCollection serviceCollection = new ServiceCollection();
- serviceCollection.AddSingleton(_options);
- ((IServiceCollection)serviceCollection).AddSingleton((IHostingEnvironment)_hostingEnvironment);
- ((IServiceCollection)serviceCollection).AddSingleton((Microsoft.Extensions.Hosting.IHostingEnvironment)_hostingEnvironment);
- serviceCollection.AddSingleton(_context);
- IConfigurationBuilder configurationBuilder = new ConfigurationBuilder().SetBasePath(_hostingEnvironment.ContentRootPath).AddConfiguration(_config);
- foreach (Action<WebHostBuilderContext, IConfigurationBuilder> configureAppConfigurationBuilderDelegate in _configureAppConfigurationBuilderDelegates)
- {
- configureAppConfigurationBuilderDelegate(_context, configurationBuilder);
- }
- IConfigurationRoot configurationRoot = configurationBuilder.Build();
- ((IServiceCollection)serviceCollection).AddSingleton((IConfiguration)configurationRoot);
- _context.Configuration = configurationRoot;
- DiagnosticListener implementationInstance = new DiagnosticListener("Microsoft.AspNetCore");
- serviceCollection.AddSingleton(implementationInstance);
- ((IServiceCollection)serviceCollection).AddSingleton((DiagnosticSource)implementationInstance);
- serviceCollection.AddTransient<IApplicationBuilderFactory, ApplicationBuilderFactory>();
- serviceCollection.AddTransient<IHttpContextFactory, HttpContextFactory>();
- serviceCollection.AddScoped<IMiddlewareFactory, MiddlewareFactory>();
- serviceCollection.AddOptions();
- serviceCollection.AddLogging();
- serviceCollection.AddTransient<IStartupFilter, AutoRequestServicesStartupFilter>();
- serviceCollection.AddTransient<IServiceProviderFactory<IServiceCollection>, DefaultServiceProviderFactory>();
- serviceCollection.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
- if (!string.IsNullOrEmpty(_options.StartupAssembly))
- {
- try
- {
- Type startupType = StartupLoader.FindStartupType(_options.StartupAssembly, _hostingEnvironment.EnvironmentName);
- if (IntrospectionExtensions.GetTypeInfo(typeof(IStartup)).IsAssignableFrom(startupType.GetTypeInfo()))
- {
- serviceCollection.AddSingleton(typeof(IStartup), startupType);
- }
- else
- {
- serviceCollection.AddSingleton(typeof(IStartup), delegate (IServiceProvider sp)
- {
- IHostingEnvironment requiredService = sp.GetRequiredService<IHostingEnvironment>();
- return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, startupType, requiredService.EnvironmentName));
- });
- }
- }
- catch (Exception source)
- {
- ExceptionDispatchInfo capture = ExceptionDispatchInfo.Capture(source);
- ((IServiceCollection)serviceCollection).AddSingleton((Func<IServiceProvider, IStartup>)delegate
- {
- capture.Throw();
- return null;
- });
- }
- }
- foreach (Action<WebHostBuilderContext, IServiceCollection> configureServicesDelegate in _configureServicesDelegates)
- {
- configureServicesDelegate(_context, serviceCollection);
- }
- return serviceCollection;
- }
- View Code
这个方法中其中就包含了注入 IConfiguration 的代码和构建 IServiceCollection 容器的代码, 当然还有一些其他的主要中间件注入啊 IApplicationBuilderFactory, 包括 HttpContextFactory 等等都在这个方法里面被 IServiceCollection 容器管理, 具体请看下图
这里讲清楚之后, 我们直接进入 UseStartup 方法中, 这个方法是注入了 Startup 的实例, 请看主要源代码
- public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType)
- {
- string name = startupType.GetTypeInfo().Assembly.GetName().Name;
- return hostBuilder.UseSetting(WebHostDefaults.ApplicationKey, name).ConfigureServices(delegate (IServiceCollection services)
- {
- if (IntrospectionExtensions.GetTypeInfo(typeof(IStartup)).IsAssignableFrom(startupType.GetTypeInfo()))
- {
- services.AddSingleton(typeof(IStartup), startupType);
- }
- else
- {
- services.AddSingleton(typeof(IStartup), delegate (IServiceProvider sp)
- {
- IHostingEnvironment requiredService = sp.GetRequiredService<IHostingEnvironment>();
- return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, startupType, requiredService.EnvironmentName));
- });
- }
- });
- }
- View Code
上面只是被 IServiceCollection 所管理 并没有真正起作用, 真正调用的是 Main 方法中的 Build().Run(), 这里的 Build 就是上面那个 IWebHostBuilder 中的主要的构建方法, 而 Run 则是正式启动应用程序和调用 Startup 中的 ConfigureServices 方法
请看代码:
分享 Program 类的过程大致就到这里了
来源: http://www.bubuko.com/infodetail-3101232.html