HTML5技术

【ASP.NET Core】运行原理之创建WebHost - Never、C(2)

字号+ 作者:H5之家 来源:H5之家 2017-12-06 11:22 我要评论( )

同时初始化WebHost对象,WebHostBuilder.Build代码: public IWebHost Build(){var hostingServices = BuildCommonServices(out var hostingStartupErrors);var applicationServices = hostingServices.Clone();var

同时初始化WebHost对象,WebHostBuilder.Build代码:

public IWebHost Build() { var hostingServices = BuildCommonServices(out var hostingStartupErrors); var applicationServices = hostingServices.Clone(); var hostingServiceProvider = hostingServices.BuildServiceProvider(); AddApplicationServices(applicationServices, hostingServiceProvider); var host = new WebHost( applicationServices, hostingServiceProvider, _options, _config, hostingStartupErrors); host.Initialize(); return host; }

在Build方法中,BuildCommonServices最为重要,将构造第一个ServiceCollection。这里我们称为hostingServices。
将包含hostEnv、Config、ApplicationBuilder、Logging、StartupFilter、Startup、Server。参考

private IServiceCollection BuildCommonServices(out AggregateException hostingStartupErrors) { if (!this._options.PreventHostingStartup) { foreach (string hostingStartupAssembly in (IEnumerable<string>) this._options.HostingStartupAssemblies) { foreach (HostingStartupAttribute customAttribute in Assembly.Load(new AssemblyName(hostingStartupAssembly)).GetCustomAttributes<HostingStartupAttribute>()) ((IHostingStartup) Activator.CreateInstance(customAttribute.HostingStartupType)).Configure((IWebHostBuilder) this); } } ServiceCollection services = new ServiceCollection(); // hostEnv _hostingEnvironment.Initialize(this._options.ApplicationName, this.ResolveContentRootPath(this._options.ContentRootPath, AppContext.BaseDirectory), this._options); services.AddSingleton<IHostingEnvironment>(this._hostingEnvironment); // config IConfigurationBuilder configurationBuilder = new ConfigurationBuilder().SetBasePath(this._hostingEnvironment.ContentRootPath).AddInMemoryCollection(this._config.AsEnumerable()); foreach (Action<WebHostBuilderContext, IConfigurationBuilder> configurationBuilderDelegate in this._configureAppConfigurationBuilderDelegates) configurationBuilderDelegate(this._context, configurationBuilder); IConfigurationRoot configurationRoot = configurationBuilder.Build(); services.AddSingleton<IConfiguration>((IConfiguration) configurationRoot); services.AddOptions(); // application services.AddTransient<IApplicationBuilderFactory, ApplicationBuilderFactory>(); services.AddTransient<IHttpContextFactory, HttpContextFactory>(); services.AddScoped<IMiddlewareFactory, MiddlewareFactory>(); // log services.AddLogging(); services.AddTransient<IStartupFilter, AutoRequestServicesStartupFilter>(); services.AddTransient<IServiceProviderFactory<IServiceCollection>, DefaultServiceProviderFactory>(); // 配置的StartupType if (!string.IsNullOrEmpty(this._options.StartupAssembly)) { Type startupType = StartupLoader.FindStartupType(this._options.StartupAssembly, this._hostingEnvironment.EnvironmentName); if (typeof (IStartup).GetTypeInfo().IsAssignableFrom(startupType.GetTypeInfo())) ServiceCollectionServiceExtensions.AddSingleton(services, typeof (IStartup), startupType); else ServiceCollectionServiceExtensions.AddSingleton(services, typeof (IStartup), new ConventionBasedStartup(StartupLoader.LoadMethods(startupType))); } // UseStartup、UseKestrel、ConfigureLogging foreach (Action<WebHostBuilderContext, IServiceCollection> servicesDelegate in this._configureServicesDelegates) servicesDelegate(this._context, (IServiceCollection) services); return (IServiceCollection) services; }

当 hostingServices 创建完成后,会马上拷贝一份applicationServices提供给WebHost使用,同时创建第一个ServiceProvider hostingServiceProvider。

host.Initialize()该方法则是初始化WebHost

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(); // RequestDelegate } WebHost.Run

创建完 WebHost 之后,便调用它的 Run 方法,而 Run 方法会去调用 WebHost 的 StartAsync 方法

  • 调用Server.Start,将Initialize方法创建的Application管道传入以供处理消息
  • 执行HostedServiceExecutor.StartAsync方法
  • public static void Run(this IWebHost host) { await host.RunAsync(cts.Token, "Application started. Press Ctrl+C to shut down."); } private static async Task RunAsync(this IWebHost host, CancellationToken token, string shutdownMessage) { await host.StartAsync(token); var hostingEnvironment = host.Services.GetService<IHostingEnvironment>(); Console.WriteLine($"Hosting environment: {hostingEnvironment.EnvironmentName}"); Console.WriteLine($"Content root path: {hostingEnvironment.ContentRootPath}"); var serverAddresses = host.ServerFeatures.Get<IServerAddressesFeature>()?.Addresses; if (serverAddresses != null) foreach (var address in serverAddresses) Console.WriteLine($"Now listening on: {address}"); if (!string.IsNullOrEmpty(shutdownMessage)) Console.WriteLine(shutdownMessage); } public virtual async Task StartAsync(CancellationToken cancellationToken = default (CancellationToken)) { Initialize(); _applicationLifetime = _applicationServices.GetRequiredService<IApplicationLifetime>() as ApplicationLifetime; _hostedServiceExecutor = _applicationServices.GetRequiredService<HostedServiceExecutor>(); var httpContextFactory = _applicationServices.GetRequiredService<IHttpContextFactory>(); var hostingApp = new HostingApplication(_application, _logger, diagnosticSource, httpContextFactory); await Server.StartAsync(hostingApp, cancellationToken).ConfigureAwait(false); _applicationLifetime?.NotifyStarted(); await _hostedServiceExecutor.StartAsync(cancellationToken).ConfigureAwait(false); } 问题解答 手工模拟一个DefaultWebHost环境 new WebHostBuilder() .UseKestrel() // 使用Kestrel服务器 .UseContentRoot(Directory.GetCurrentDirectory()) // 配置根目录 会在ConfigurationBuilder、 IHostingEnvironment(后续其他中间件) 和 WebHostOptions(WebHost)用到。 .ConfigureAppConfiguration((context, builder) => builder.AddJsonFile("appsetting.json", true, true)) // 添加配置源 .ConfigureLogging(builder => builder.AddConsole()) // 添加日志适配器 .UseStartup<Startup>() // 选择Startup .Build().Run(); // 生成WebHost 并 启动

    本文链接:

    posted @

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • ASP.NET没有魔法——ASP.NET Identity 的“多重”身份验证代码篇 - 7m鱼

      ASP.NET没有魔法——ASP.NET Identity 的“多重”身份验证代码篇 - 7

      2017-12-01 18:01

    • Entity Framework Core 使用HiLo生成主键 - Sweet-Tang

      Entity Framework Core 使用HiLo生成主键 - Sweet-Tang

      2017-11-27 10:14

    • 使用AspectCore动态代理 - Lemon丶

      使用AspectCore动态代理 - Lemon丶

      2017-11-21 11:01

    • 极简版ASP.NET Core学习路径及教程 - 腾飞(Jesse)

      极简版ASP.NET Core学习路径及教程 - 腾飞(Jesse)

      2017-11-17 14:02

    网友点评
    r