.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() { // ... } }
关于其他的接口或者方法我们之后的文章再一一介绍。