.Net Host详细介绍
分类: .Net技术 ◆ 标签: #基础 #.Net #.Net Host ◆ 发布于: 2023-06-15 15:31:43

我们前面简单的介绍了什么是.Net Host
, 我们这一节详细的学习和了解一下Host
的内容。
我们先通过.Net Cli
创建一个demo
,认识一下什么是Host
。
在你的电脑上打开终端,依次运行如下的命令:
dotnet new webapp -o WebDemo1
cd WebDemo1
code .
基于.Net 6
的Host
模型
使用VS Code
打开目录后,查看文件Program.cs
的内容如下:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorPages(); var app = builder.Build(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run();
这是基于.Net 6
的用于创建Web
应用的模板,关于.Net 6
中提出的WebApplicationBuilder
和WebApplication
概念,您可以参考我之前的文档:https://www.dotnetdeveloper.cn/dotnet-guide/dotnet-6-webapplication-builder-deep-learning, 在这个文档里详细的论述了从WebHost
到Generic Host
再到.Net 6
的WebApplicationBuilder
。
为了探索.Net 6
的Host
模型,您可以尝试builder.Host
以及builder.WebHost
, WebApplicationBuilder
的两个属性,Host
和WebHost
统一了两种模型,另外关于新模型,您也可以通过如下的文章仔细学习:
- https://www.dotnetdeveloper.cn/dotnet-guide/dotnet-6-deep-learning-webapplication-builder
- https://www.dotnetdeveloper.cn/dotnet-guide/dotnet-6-how-to-use-webapplication
如上是.Net6
的host模型,我们接下来看看Generic Host
的代码:
基于Generic Host
的模型
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>(); }; } }
从Generic Host
的模型可以看到我们是通过静态类Host
来创建一个IHostBuilder
的实例,然后通过IHostBuilder
的方法Build()
来创建一个IHost
的实现,并通过IHost
的Run()
来运行一个Host
。 而需要注意的是基于.Net 6
的WebApplicationBuilder
的方法Builder()
返回的是一个WebApplication
的实例, 它代表的是一个基于Web
的应用。
至于在Generic Host
之前的WebHost
模型,完全是为了兼容之前的Asp.net Core
框架而存在的,现如今完全可以不用考虑这个模型。
创建Host
模型的时候做了哪些事?
虽然.Net 6
推出了基于WebApplicationBuilder
以及WebApplication
的Host
模型(实际上这么说并不准确,因为实际上并没有创造新的Host
模型,仅仅是为了Web
开发的需要,使用了两个包装). Generic Host
模型仍然在.Net 6
中还是可以使用的,例如在.Net 6
中开发非Web
的应用,那么就需要直接使用Generic Host
的模板和模型。
我们在看一下如何设置Genric Host
:
Host.CreateDefaultBuilder(args) .ConfigureServices((_, services) => services.AddHostedService<Your Service Class>()) .Build() .RunAsync();
如上创建一个Generic Host
, 同时通过扩展方法AddHostedService
添加用户自行编写的基于Host
的服务,该服务实现IHostedService
接口。
如果我们要配置一个基于.Net Host
的Web
应用该如何设定呢?
Host.CreateDefaultBuilder(args) .ConfigureServices((_, services) => services.AddHostedService<Your Service Class>()) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }) .Build() .RunAsync();
添加一个ConfigureWebHostDefaults
的函数用于配置基于Web
的应用。
CreateDefaultBuilder
都干了啥?
在静态类Host
上调用CreateDefaultBuilder
主要处理如下的事情:
- 将项目运行的根目录
content root
设为当前的目录(由命令GetCurrentDirectory
返回) - 从环境变量以及命令行中读入
Host
的配置,需要注意的是环境变量名使用DOTNET_
为前缀。 - 从如下列表中读入应用的配置:
- 配置文件
appsettings.json
- 配置文件
appsettings.{Environment}.json
- 如果应用运行在
Development
环境下从User secrets
里读入配置。 - 环境变量
- 命令行参数。
- 配置文件
- 向系统添加如下的日志组件:
- Console
- Debug
- EventSource
- Eventlog (只在windows下启用)
- 启用依赖注入容器,并添加
Scope
验证。
ConfigureWebHostDefaults
干了些什么?
我们之前已经清楚的表明了,在调用ConfigureWebhostDeault()
方法主要是为了给Host
添加基于Web
的应用,出了这个之外,还有如下的列表:
- 从环境变量读入
WebHost
的配置,环境变量使用默认的前缀ASPNETCORE_
- 设置
Kestrel
为Web服务器,从上一步的WebHost
配置中读入配置。 - 添加
Host Filter
中间件 - 如果设置了环境变量
ASPNETCORE_FORWARDHEADERS_ENABLE
为true
时,添加Forward Headers
中间件 - 启用
IIS
集成。
Host
启用的依赖注入服务添加了哪些框架自带的服务
我们前面讨论了在Generic Host
启动的时候会启用依赖注入容器,同时作为框架也会自动加入更多的服务:
- IHostApplicationLifetime
- IHostLifetime
- IHostEnvironment/IWebHostEnvironment
关于这些服务我们可以初略的看一下每个服务的作用。
IHostApplicationLifetime
在用户的代码中可以通过注入IHostApplicationLifetime
的实例, 可以用于处理用户代码随着host的post-startup和shutdown事件。
这个接口定义了三个属性用于处理应用的started
、stopping
, stopped
事件。
来看一个简单的例子:
需要注意的是接口IHostedService
, 这个接口用于定义一个基于Host
实现的服务,后面的章节我们会详细的学习这个接口。
public class HostApplicationLifetimeEventsHostedService : IHostedService { private readonly IHostApplicationLifetime _hostApplicationLifetime; public HostApplicationLifetimeEventsHostedService( IHostApplicationLifetime hostApplicationLifetime) => _hostApplicationLifetime = hostApplicationLifetime; public Task StartAsync(CancellationToken cancellationToken) { _hostApplicationLifetime.ApplicationStarted.Register(OnStarted); _hostApplicationLifetime.ApplicationStopping.Register(OnStopping); _hostApplicationLifetime.ApplicationStopped.Register(OnStopped); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; private void OnStarted() { // ... } private void OnStopping() { // ... } private void OnStopped() { // ... } }
关于其他的接口或者方法我们之后的文章再一一介绍。