1 直接上结论:
那就是asp.net core Web主机(即Web Host) 是寄宿在Host(也叫做Generic Host,泛型主机)上的。主机寄宿是靠实现IHostedService接口达到的,然后调用AddHostedService()方法达到的,类似下面这样:
// GenericWebHostBuilder类的构造函数会调用下面这句话
services.AddHostedService<GenericWebHostService>();
这就是通过依赖注入,往Host上注入了Web服务。
2 分析源码
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
如果不调用ConfigureWebHostDefaults(…)方法,就不会有Web服务,因此Web服务是通过调用ConfigureWebHostDefaults()方法而来的,这个方法在GenericHostBuilderExtensions.cs文件里定义:
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore;
namespace Microsoft.Extensions.Hosting
{
/// <summary>
/// Extension methods for configuring the IWebHostBuilder.
/// </summary>
public static class GenericHostBuilderExtensions
{
/// <summary>
/// Initializes a new instance of the <see cref="IWebHostBuilder"/> class with pre-configured defaults.
/// </summary>
/// <remarks>
/// The following defaults are applied to the <see cref="IWebHostBuilder"/>:
/// use Kestrel as the web server and configure it using the application's configuration providers,
/// configure the <see cref="IWebHostEnvironment.WebRootFileProvider"/> to map static web assets when <see cref="IHostEnvironment.EnvironmentName"/> is 'Development' using the entry assembly,
/// adds the HostFiltering middleware,
/// adds the ForwardedHeaders middleware if ASPNETCORE_FORWARDEDHEADERS_ENABLED=true,
/// and enable IIS integration.
/// </remarks>
/// <param name="builder">The <see cref="IHostBuilder" /> instance to configure</param>
/// <param name="configure">The configure callback</param>
/// <returns>The <see cref="IHostBuilder"/> for chaining.</returns>
public static IHostBuilder ConfigureWebHostDefaults(this IHostBuilder builder, Action<IWebHostBuilder> configure)
{
return builder.ConfigureWebHost(webHostBuilder =>
{
WebHost.ConfigureWebDefaults(webHostBuilder);
configure(webHostBuilder);
});
}
}
}
从上面源码可以发现ConfigureWebHostDefaults()继续调用builder.ConfigureWebHost()方法,那么我们继续看一下ConfigureWebHost()方法都有些什么,这个方法在
GenericHostWebHostBuilderExtensions.cs文件里定义:
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Internal;
namespace Microsoft.Extensions.Hosting
{
public static class GenericHostWebHostBuilderExtensions
{
public static IHostBuilder ConfigureWebHost(this IHostBuilder builder, Action<IWebHostBuilder> configure)
{
var webhostBuilder = new GenericWebHostBuilder(builder);
configure(webhostBuilder);
return builder;
}
}
}
现在,我们可以发现终于new了一个webhostBuilder这样的东西,从名字里可以猜测到,它肯定是用于建造web host的,那么具体是怎么嵌入Host的呢,这就需要进一步查看GenericWebHostBuilder类的构造函数,由于这个构造函数代码很长,这里就不贴了,我们可以在GenericWebHostBuilder类的构造函数发现文章开头的AddHostedService()这样的代码,这就是将Web Host注入到Generic Host当中,因此Web Host是由Generic Host启动的,Host是宿主,WebHost只是个"寄生虫"。
3 结个尾
这里多说一句,我们自己也可以建造自己的主机(host)寄宿到Generic Host上,但是不是什么玩意都可以寄宿的,寄宿有规范的,这个规范就是得是实现IHostedService接口的主机才行,因此,我们很容易猜想的到GenericWebHostService类就是Web Host实现了IHostedService的一个类,事实也是如此。
4 回顾下微软原话
主机(Generic Host)定义
主机(Generic Host)是封装应用资源的对象,例如:
- 依赖关系注入 (DI)
- Logging
- Configuration
- IHostedService 实现
当主机(Generic Host)启动时,它将对在托管服务的服务容器集合中注册的 IHostedService 的每个实现调用 IHostedService.StartAsync。 在 web 应用中,其中一个 IHostedService 实现是启动 HTTP 服务器实现的 web 服务。