这是ASP.NET Core新核心对象系列的第二篇,上一篇 WebHost准备阶段 我们讲到了WebHostBuilder的初始化及配置。我们给WebHostBuilder进行以下配置

  1. UseKestrel 设置Kestrel为HttpServer
  2. ConfigureAppConfiguration 设置了配置文件
  3. ConfigureLogging 配置了日志处理器,添加了 Debug和控制台两种方式
  4. UseStartup 指定了Startup类

有了一个WebHostBuilder之后,我们就可以调用它的Build方法来构建一个WebHost。
我们可以先来看一下Build方法的代码

// 初始化DI
var hostingServices = BuildCommonServices(out var hostingStartupErrors);
var applicationServices = hostingServices.Clone();
var hostingServiceProvider = hostingServices.BuildServiceProvider();

// 构造 WebHost 
var host = new WebHost(
    applicationServices,
    hostingServiceProvider,
    _options,
    _config,
    hostingStartupErrors);

// 初始化host 
host.Initialize();

return host;

BuildCommonServices

这是 WebHostBuild方法执行的第一个方法,主要是new ServiceCollection 以及完成了以下几个基础实例的注册:

  • IApplicationBuilderFactory
  • IHttpContextFactory
  • IMiddlewareFactory
  • IStartupFilter
  • IServiceProviderFactory<IServiceCollection>
  • IStartup

其实将IStartup注册到 DI,利用了两种方式 。如果我们在WebHostBuilder中指定的 Startup.cs继承自 IStartup接口,则直接绑定到IStartup。

if (typeof(IStartup).GetTypeInfo()
  .IsAssignableFrom(startupType.GetTypeInfo()))
{
    services.AddSingleton(typeof(IStartup), startupType);
}

否则,需要 按照命名规则来构造一个Startup。

services.AddSingleton(typeof(IStartup), sp =>
{
var hostingEnvironment = 
    sp.GetRequiredService<IHostingEnvironment>();

var methods = StartupLoader.LoadMethods(
    sp, 
    startupType, 
    hostingEnvironment.EnvironmentName);
return new ConventionBasedStartup(methods);
});

Host的初始化

Host的初始化是我们这次要讲的重点,因为它完成了整个Http管道的构建。

 if (_application == null)
    {
        _application = BuildApplication();
    }

这个_application即是一个RequestDelegate。参数为一个HttpContext。

public delegate Task RequestDelegate(HttpContext context);

我们来看一下BuildApplication方法有7步,后面的五步总结起来是构造IAapplicationBuilder并用Startup.cs的Configure方法构造一个我们上面讲的这个RequestDeleaget。

IApplicationBuilder 

IApplicationBuilder定义在HttpAbstractions这个项目里面,HttpAbstractions是ASP.NET Core在 Githab上的一个子项目,也是ASP.NET Core的重要组成部分,它定义了很多ASP.NET Core中关于HTTP处理整个过程中的行为。 IApplicationBuilder就算一个。

它主要包括以几个重要的属性:

我们在Startup.cs中看到的Configure方法给的参数就是这个IApplicationBuilder,而这个方法是用来添加Middleware的。

public void Configure(IApplicationBuilder app) { 

  // 相当于 List<Middleware>().add(某个middleware)
  app.Use(某个Middleware) 
}
它决定了我们的一个请求会经历哪些步骤最终返回给客户端。但是它的生命很短暂,毕竟它只是个Builder,在它完成管道的构建之后,它就生命就结束了。构建管理的过程很简单:
  • 从DI中获取IApplicationBuilderFactory 实例 builderFactory
  • builderFactory.CreateBuilder() 得到 ApplicationBuilder
  • 获取IStartupFilter实例
  • 调用IStartupFilter实例的Configure方法,传处第二步得到的ApplicationBuilder
  • 调用 ApplicationBuilder的Builder方法,也就是我们上面讲的,把所有注册的Middleware串起来最后返回一个RequestDelegate

WebHost.Start

在我们的WebHost初始化完成之后,它的Start方法会被调用来启动IServer的端口监听,并开始处理Http请求。这是WebHost的第三阶段:启动过程 。我们将在周四晚上8点的下一篇中详细讲述。

分类: 技术随笔

1 条评论

Allen · 2018年2月27日 下午2:59

能不能再加几个图呢?比如顺序流程图,帮助新手理解,文章讲的很好,总结的也很棒,感谢

发表评论

电子邮件地址不会被公开。 必填项已用*标注