测试代码运行环境:
OS:Ubuntu 18.04 64bit
.NET Core SDK Version: 3.1.101
源代码版本:release/3.1
起点 - Program.cs
首先通过 .NET Core CLI 指令新建一个空的模板 ASP.NET Core 应用程序
dotenet new web -n SampleWeb
指令会新建一个全新的 ASP.NET Core模板应用程序,文件结构如下:
1 | SampleWeb |
Program.cs包含了配置及启动 ASP.NET Core 应用程序的全部代码,一共只有寥寥几行,非常简洁高效,我们今天的主角IWebHostBuilder、IWebHost就在其中。
ASP.NET CORE 3.0 将早期版本的WebHostBuilder替换成了全新的基于GenericHost的HostBuilder,可以为 ASP.NET Core 应用程序与非WEB应用程序更好的集成,共享更多基础代码。具体信息可前往What’s new in ASP.NET Core 3.0查看。
1 | //...省略部分代码 |
Host.CreateDefaultBuilder()方法会创建一个默认的HostBuilder对象,配置Startup类作为HOST启动后的应用程序配置入口点。
完成HostBuilder的创建及配置后,只需要按照顺序调用Build()方法返回IHost对象,及Run()方法启动IHost,应用程序就启动完成了。
应用程序元数据的配置 - IHostBuilder及实现
IHostBuilder
接口:
1 | namespace Microsoft.Extensions.Hosting |
IHostBuilder 定义在dotnet/extensions项目中(GITHUB REPO)。
项目名称为:Microsoft.Extensions.Hosting.Abstractions。
名称空间Microsoft.Extensions.Hosting
源代码
IHostBuilder一共定义了八个接口成员,下表展示了这些接口成员的主要用途:
接口成员 | 成员类型 | 用途 |
---|---|---|
Properties | 属性 | 用于自定义组件在创建IHost对象过程中共享数据 |
ConfigureHostConfiguration | 方法 | 用于配置IHostBuilder在创建IHost对象过程中需要使用到的各种配置信息,在本方法中会初始化Microsoft.Extensions.Hosting.IHostEnvironment对象 |
ConfigureAppConfiguration | 方法 | 用于配置应用程序初始化及运行过程中所需的配置项 |
ConfigureServices | 方法 | 注册应用程序所需的各种服务 |
UseServiceProviderFactory(及重载) | 方法 | 用于替换系统默认的IOC容器(Service Provider) |
ConfigureContainer | 方法 | 用于配置IOC容器实例的细节 |
Build | 方法 | 生成IHost对象 |
在创建IHost对象的过程中,我们可以定制应用程序所需的各种基本配置,并通过这些接口成员注入到IHostBuilder对象中。
IHostBuilder的默认实现
IHostBuilder
的默认实现:HostBuilder
HostBuilder 定义在dotnet/extensions项目中(GITHUB REPO)。
项目名称为:Microsoft.Extensions.Hosting。
名称空间Microsoft.Extensions.Hosting
源代码
在HostBuilder的默认实现中,定义了一系列对应的List<Action>
对象来存储用户注册到ConfigureHostConfiguration
、ConfigureAppConfiguration
、ConfigureServices
等方法中的配置函数
1 | private List<Action<IConfigurationBuilder>> _configureHostConfigActions = new List<Action<IConfigurationBuilder>>(); |
下面我们看一下Build方法的实现;
1 | public IHost Build() |
Build方法的内容也很简单,只有一个基本检查和五个步骤。
1、首先检查是否重复创建了IHost对象,每个IHostBuilder对象只能运行一次Build方法,否则抛出异常,确保我们不会重复创建IHost对象。
2、第二步初始化创建IHost对象过程中需要使用到的基本配置信息。
3、第三步初始化应用程序的Microsoft.Extensions.Hosting.IHostEnvironment
对象,用来向应用程序提供程序运行环境信息(Development、Stage、Production等)。
4、第四步初始化(根据第二部初始化的基本配置信息)创建IHost对象所需要的所有上下文对象。
5、最后创建IOC容器,并将默认的IHost对象(Microsoft.Extensions.Hosting.Internal.Host
)注入到IOC容易中,然后将IHost对象从IOC容器里取出并返回给方法的调用方。
至此,IHostBuilder
就完成了它的全部使命。
应用程序宿主 - IHost及实现
IHost
接口
1 | public interface IHost : IDisposable |
IHost 定义在dotnet/extensions项目中(GITHUB REPO)。
项目名称为:Microsoft.Extensions.Hosting.Abstractions。
名称空间Microsoft.Extensions.Hosting
源代码
相较于IHostBuilder
接口,IHost
接口的定义要简单的多,只有三个成员对象:
接口成员 | 成员类型 | 用途 |
---|---|---|
Services | 属性 | 用于获取注册在IOC容器中的服务 |
StartAsync | 方法 | 启动应用程序 |
StopAsync | 方法 | 停止应用程序 |
IHost的默认实现
IHost
的默认实现:Internal.Host
HostBuilder 定义在dotnet/extensions项目中(GITHUB REPO)。
项目名称为:Microsoft.Extensions.Hosting。
名称空间Microsoft.Extensions.Hosting.Internal
源代码
StartAsync
方法的实现:
1 | public async Task StartAsync(CancellationToken cancellationToken = default) |
StartAsync
方法将注册到HostBuilder上下文中的IHostedService
对象按照注册时的先后顺序执行IHostedService.StartAsync()
方法进行启动。
将所有的IHostedService
对象执行启动完毕后,通过应用程序生命周期管理对象IApplicationLifetime
通知应用程序,启动就完成了。
StopAsync
方法的实现:
1 | public async Task StopAsync(CancellationToken cancellationToken = default) |
StopAsync
方法与StartAsync
方法基本类型,首先通过应用程序生命周期管理对象IApplicationLifetime
通知应用程序即将开始停止服务,然后一次调用IHostedService
对象停止服务的运行,最后通知应用程序已完成结束方法。
ASP.NET Core 的扩展方法
从默认的IHostBuilder
及默认的IHost
对象源代码中我们可以发现,IHostBuidler
及IHost
对象仅仅提供了创建现代化的应用程序(基于依赖注入、控制反转等编程思想)的最基础支持,而仅靠默认的实现我们还无法构建一个现代WEB应用程序,因此ASP.NET Core应用程序框架在默认的IHostBuilder
及IHost
对象之上,提供了扩展方法,帮助我们构建一个基本的现代WEB应用程序。
扩展方法 - CreateDefaultBuilder
CreateDefaultBuilder 定义在dotnet/extensions项目中(GITHUB REPO)。
项目名称为:Microsoft.Extensions.Hosting。
名称空间Microsoft.Extensions.Hosting
源代码
CreateDefaultBuilder
方法:
1 | public static IHostBuilder CreateDefaultBuilder(string[] args) |
从源代码中我们可以看到,CreateDefaultBuilder
方法配置了默认的ContentRoot配置项,用于指示应用程序从哪里获取静态文件和WEB程序的根目录。加载了DOTNET_
前缀的系统环境变量,并从appsettings.json
和appsettings.{env.EnvironmentName}.json
文件中加载应用程序配置信息。配置日志组件,并添加了日志系统的输出路径,而且针对Windows操作系统额外添加了日志的拦截器和WindowsEvent组件的日志输出路径。
扩展方法 - ConfigureWebHostDefaults
CreateDefaultBuilder有一个较长的调用链,最终实际对ASP.NET Core应用程序进行配置的方法是
WebHost.ConfigureWebDefaults
方法WebHost.ConfigureWebDefaults
方法定义在dotnet/aspnetcore项目中(GITHUB REPO)。
项目名称为:Microsoft.AspNetCore
名称空间Microsoft.AspNetCore
源代码
CreateDefaultBuilder
方法:
1 | internal static void ConfigureWebDefaults(IWebHostBuilder builder) |
从源代码中我们可以看到,ConfigureWebDefaults
方法配置了Web Server 组件Kestrel
用来处理HTTP通信,加载了CORS基础配置,配置了ForwardedHeaders(用于支持代理服务如Nginx等),添加了基础的路由组件并配置了IIS的支持组件。
于是ASP.NET Core应用程序此时已经可以支持HTTP通信,并且无需额外配置就可以运行在代理服务器之上。还可以根据请求的URI信息进行路由分配,查找对应的Controller类/Action方法。
扩展方法 - UserStartup
UserStartup
有一个较长的调用链,最终实际对ASP.NET Core应用程序进行配置的方法是WebHostBuilderExtensions.UserStartup
方法WebHostBuilderExtensions.UserStartup
方法定义在dotnet/aspnetcore项目中(GITHUB REPO)。
项目名称为:Microsoft.AspNetCore.Hosting
名称空间Microsoft.AspNetCore.Hosting
源代码
UserStartup
方法
1 | public static IWebHostBuilder UseStartup( |
UserStartup
方法将会在应用程序中查找注册的Startup
类,并执行Startup
类的配置方法对ASP.NET Core应用程序执行最后的,用户层面的最终配置,在Startup
类中,我们将详细的配置我们的ASP.NET Core应用程序已满足我们对业务支撑的需要。这也是绝大多数开发者首次接触到的ASP.NET Core应用程序配置的地点。
值得注意的是,在UserStartup
方法中,会首先查找声明了IStartup
接口的Startup
类(如果此处传入的IWebHostBuiler
声明了ISupportStartup
接口的话。)。因此除了将ASP.NET Core应用程序直接编译成可执行程序外,我们也可以将ASP.NET Core应用程序写在类库类型的项目中,由类库的使用者来帮助我们启动ASP.NET Core应用程序。
终点 - Startup.cs
Startup
类:
1 | namespace SmapleWeb |
空ASP.NET Core项目的Startup类非常简单,实现了一个空的ConfigureServices
方法,在这个方法里,我们可以注入我们需要使用的各种服务类或基础组件类。
并且实现了Configure
方法,注册了基础路由组件和终结点组件,能够处理访问WEB ROOT的路径的请求,并返回Hello World!
以上就是ASP.NET Core应用程序关于HOST类的全部源代码,我们可以看到ASP.NET Core应用程序的宿主类的实现并不复杂,并且除了支持ASP.NET Core应用程序之外,还可以支持我们方便的写出各种类型的服务程序,只需要我们根据实际需要实现一些基本类型即可。