写在前面
ASP .NET Core 中的通用主机构建器是在 v2.1 中引入的, 应用在启动时构建主机, 主机作为一个对象用于封装应用资源以及应用程序启动和生存期管理. 其主要功能包括配置初始化 (包括加载配置以及配置转换为通用的键值对格式), 创建托管环境和 Host 通用上下文, 依赖注入等.
在. NET Core 3.0 中采用了 IHostBuilder 用于创建 Host, 同时也不再建议使用 web 主机, 而建议使用泛型主机, 主要原因是原有的通用主机仅适用于非 HTTP 负载, 为了提供更加广泛的主机方案, 需要将 HTTP 管道与 Web 主机的接口分离出来. 但 Web 主机仍会向后兼容.
.NET Core 3.0 中创建通用主机
以下代码是 V3.0 中提供的模板代码, 可以看到在创建主机的过程中, 已经摒弃了 WebHostBuilder 的创建方式
- public class Program
- {
- public static void Main(string[] args)
- {
- CreateHostBuilder(args).Build().Run();
- } 7:
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .ConfigureWebHostDefaults(webBuilder =>
- {
- webBuilder.UseStartup<Startup>();
- });
- }
而在. NET Core 2.X 中
- 1: public class Program
- 2: {
- 3: public static void Main(string[] args)
- 4: {
- 5: CreateWebHostBuilder(args).Build().Run();
- 6:
- } 7:
- 8: public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
- 9: WebHost.CreateDefaultBuilder(args)
- 10: .UseStartup<Startup>();
- 11:
- }
V3.0 模板中提供的 CreateHostBuilder() 方法看起来非常类似于 V2.X 中的 CreateWebHostBuilder().
其主要区别在于对 WebHost.CreateDefaultBuilder() 由 Host.CreateDefaultBuilder() 替换. 使用 CreateDefaultBuilder() 辅助方法可以非常轻松地从 v2.x 切换到 v3.0.
另一个区别是关于 ConfigureWebHostDefaults() 的调用. 由于新的主机构建器是通用主机构建器, 因此我们必须让它知道我们打算为 Web 主机配置默认设置. 这些默认配置我们可以在 ConfigureWebHostDefaults() 方法中实现
CreateDefaultBuilder
该方法 Microsoft.Extensions.Hosting.Host 中, 它是一个静态类, 里面有两个方法, 一个有参的 CreateDefaultBuilder(string[] args), 一个是无参的.
无参方法源码如下,
- public static IHostBuilder CreateDefaultBuilder() =>
- CreateDefaultBuilder(args: null);
可以看到该方法实际上是设置了默认值.
IHostBuilder CreateDefaultBuilder(string[] args) 方法主要有以下功能:
创建 HostBuilder 对象
1: var builder = new HostBuilder();
指定 Host 要使用的内容根目录
1: builder.UseContentRoot(Directory.GetCurrentDirectory());
配置初始化 (环境变量, appsettings.JSON,User Secrets)
- builder.ConfigureHostConfiguration(config =>
- {
- config.AddEnvironmentVariables(prefix: "DOTNET_");
- if (args != null)
- {
- config.AddCommandLine(args);
- } 8: }); 9:
- builder.ConfigureAppConfiguration((hostingContext, config) =>
- {
- var env = hostingContext.HostingEnvironment;
- config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
- .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
- if (env.IsDevelopment() && !string.IsNullOrEmpty(env.ApplicationName))
- {
- var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
- if (appAssembly != null)
- {
- config.AddUserSecrets(appAssembly, optional: true);
- } 24: } 25:
- config.AddEnvironmentVariables();
- if (args != null)
- {
- config.AddCommandLine(args);
- } 32: })
日志
- .ConfigureLogging((hostingContext, logging) =>
- {
- logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
- logging.AddConsole();
- logging.AddDebug();
- logging.AddEventSourceLogger();
- })
在开发环境模式下启用作用域验证
- 1: .UseDefaultServiceProvider((context, options) =>
- 2: {
- 3: var isDevelopment = context.HostingEnvironment.IsDevelopment();
- 4: options.ValidateScopes = isDevelopment;
- 5: options.ValidateOnBuild = isDevelopment;
- 6:
- });
- Build
Build() 方法是 Microsoft.Extensions.Hosting 中, 并且该方法只会执行一次, 当然这种一次只是在同一个实例里面
- public IHost Build()
- {
- if (_hostBuilt)
- {
- throw new InvalidOperationException("Build can only be called once.");
- }
- _hostBuilt = true;
- BuildHostConfiguration();
- CreateHostingEnvironment();
- CreateHostBuilderContext();
- BuildAppConfiguration();
- CreateServiceProvider();
- return _appServices.GetRequiredService<IHost>();
- }
该方法主要是包括以下功能:
创建 HostingEnvironment
创建 HostBuilderContext
配置初始化及格式标准化
- DI(创建 IHostEnvironment,IHostApplicationLifetime,IHostLifetime,IHost)
- Run
Run 方法运行应用程序并阻止调用线程, 直到主机关闭
- public static void Run(this IHost host)
- {
- host.RunAsync().GetAwaiter().GetResult();
- }
以下是 RunAsync 的源码, 此处可以通过设置 CancellationToken 的值, 使应用程序自动关闭
- 1: public static async Task RunAsync(this IHost host, CancellationToken token = default)
- 2: {
- 3: try 4: {
- 5: await host.StartAsync(token);
- 6:
- 7: await host.WaitForShutdownAsync(token);
- 8:
- } 9: finally 10: {
- 11: #if DISPOSE_ASYNC
- 12: if (host is IAsyncDisposable asyncDisposable)
- 13: {
- 14: await asyncDisposable.DisposeAsync();
- 15:
- } 16: else 17: #endif 18: {
- 19: host.Dispose();
- 20:
- } 21: 22:
- } 23:
- }
来源: https://www.cnblogs.com/edison0621/p/11025310.html