前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.NET Core 3.0 之初识Host源码

.NET Core 3.0 之初识Host源码

作者头像
Edison.Ma
发布2019-07-19 17:53:24
7270
发布2019-07-19 17:53:24
举报
文章被收录于专栏:DotNet Core圈圈DotNet Core圈圈

写在前面

ASP .NET Core中的通用主机构建器是在v2.1中引入的,应用在启动时构建主机,主机作为一个对象用于封装应用资源以及应用程序启动和生存期管理。其主要功能包括配置初始化(包括加载配置以及配置转换为通用的键值对格式),创建托管环境和Host通用上下文、依赖注入等。

在.NET Core 3.0中采用了IHostBuilder用于创建Host,同时也不再建议使用Web主机,而建议使用泛型主机,主要原因是原有的通用主机仅适用于非HTTP负载,为了提供更加广泛的主机方案,需要将HTTP管道与Web主机的接口分离出来。但Web主机仍会向后兼容。

.NET Core 3.0中创建通用主机

以下代码是V3.0中提供的模板代码,可以看到在创建主机的过程中,已经摒弃了WebHostBuilder的创建方式

代码语言:javascript
复制
   1:  public class Program
代码语言:javascript
复制
   2:  {
代码语言:javascript
复制
   3:      public static void Main(string[] args)
代码语言:javascript
复制
   4:      {
代码语言:javascript
复制
   5:          CreateHostBuilder(args).Build().Run();
代码语言:javascript
复制
   6:      }
代码语言:javascript
复制
   7:   
代码语言:javascript
复制
   8:      public static IHostBuilder CreateHostBuilder(string[] args) =>
代码语言:javascript
复制
   9:          Host.CreateDefaultBuilder(args)
代码语言:javascript
复制
  10:              .ConfigureWebHostDefaults(webBuilder =>
代码语言:javascript
复制
  11:              {
代码语言:javascript
复制
  12:                  webBuilder.UseStartup<Startup>();
代码语言:javascript
复制
  13:              });
代码语言:javascript
复制
  14:  }

而在.NET Core 2.X中

代码语言:javascript
复制
   1:  public class Program
代码语言:javascript
复制
   2:  {
代码语言:javascript
复制
   3:     public static void Main(string[] args)
代码语言:javascript
复制
   4:     {
代码语言:javascript
复制
   5:        CreateWebHostBuilder(args).Build().Run();
代码语言:javascript
复制
   6:     }
代码语言:javascript
复制
   7:   
代码语言:javascript
复制
   8:     public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
代码语言:javascript
复制
   9:        WebHost.CreateDefaultBuilder(args)
代码语言:javascript
复制
  10:           .UseStartup<Startup>();
代码语言:javascript
复制
  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),一个是无参的。

无参方法源码如下,

代码语言:javascript
复制
   1:  public static IHostBuilder CreateDefaultBuilder() =>
代码语言:javascript
复制
   2:              CreateDefaultBuilder(args: null);

可以看到该方法实际上是设置了默认值。

IHostBuilder CreateDefaultBuilder(string[] args)方法主要有以下功能:

创建HostBuilder对象

代码语言:javascript
复制
   1:  var builder = new HostBuilder();

指定Host要使用的内容根目录

代码语言:javascript
复制
   1:  builder.UseContentRoot(Directory.GetCurrentDirectory());

配置初始化(环境变量、appsettings.json、User Secrets)

代码语言:javascript
复制
   1:  builder.ConfigureHostConfiguration(config =>
代码语言:javascript
复制
   2:  {
代码语言:javascript
复制
   3:      config.AddEnvironmentVariables(prefix: "DOTNET_");
代码语言:javascript
复制
   4:      if (args != null)
代码语言:javascript
复制
   5:      {
代码语言:javascript
复制
   6:          config.AddCommandLine(args);
代码语言:javascript
复制
   7:      }
代码语言:javascript
复制
   8:  });
代码语言:javascript
复制
   9:   
代码语言:javascript
复制
  10:  builder.ConfigureAppConfiguration((hostingContext, config) =>
代码语言:javascript
复制
  11:  {
代码语言:javascript
复制
  12:      var env = hostingContext.HostingEnvironment;
代码语言:javascript
复制
  13:   
代码语言:javascript
复制
  14:      config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
代码语言:javascript
复制
  15:            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
代码语言:javascript
复制
  16:   
代码语言:javascript
复制
  17:      if (env.IsDevelopment() && !string.IsNullOrEmpty(env.ApplicationName))
代码语言:javascript
复制
  18:      {
代码语言:javascript
复制
  19:          var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
代码语言:javascript
复制
  20:          if (appAssembly != null)
代码语言:javascript
复制
  21:          {
代码语言:javascript
复制
  22:              config.AddUserSecrets(appAssembly, optional: true);
代码语言:javascript
复制
  23:          }
代码语言:javascript
复制
  24:      }
代码语言:javascript
复制
  25:   
代码语言:javascript
复制
  26:      config.AddEnvironmentVariables();
代码语言:javascript
复制
  27:   
代码语言:javascript
复制
  28:      if (args != null)
代码语言:javascript
复制
  29:      {
代码语言:javascript
复制
  30:          config.AddCommandLine(args);
代码语言:javascript
复制
  31:      }
代码语言:javascript
复制
  32:  })

日志

代码语言:javascript
复制
   1:  .ConfigureLogging((hostingContext, logging) =>
代码语言:javascript
复制
   2:  {
代码语言:javascript
复制
   3:      logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
代码语言:javascript
复制
   4:      logging.AddConsole();
代码语言:javascript
复制
   5:      logging.AddDebug();
代码语言:javascript
复制
   6:      logging.AddEventSourceLogger();
代码语言:javascript
复制
   7:  })

在开发环境模式下启用作用域验证

代码语言:javascript
复制
   1:  .UseDefaultServiceProvider((context, options) =>
代码语言:javascript
复制
   2:  {
代码语言:javascript
复制
   3:      var isDevelopment = context.HostingEnvironment.IsDevelopment();
代码语言:javascript
复制
   4:      options.ValidateScopes = isDevelopment;
代码语言:javascript
复制
   5:      options.ValidateOnBuild = isDevelopment;
代码语言:javascript
复制
   6:  });

Build

Build()方法是Microsoft.Extensions.Hosting中,并且该方法只会执行一次,当然这种一次只是在同一个实例里面

代码语言:javascript
复制
   1:  public IHost Build()
代码语言:javascript
复制
   2:  {
代码语言:javascript
复制
   3:      if (_hostBuilt)
代码语言:javascript
复制
   4:      {
代码语言:javascript
复制
   5:          throw new InvalidOperationException("Build can only be called once.");
代码语言:javascript
复制
   6:      }
代码语言:javascript
复制
   7:      _hostBuilt = true;
代码语言:javascript
复制
   8:   
代码语言:javascript
复制
   9:      BuildHostConfiguration();
代码语言:javascript
复制
  10:      CreateHostingEnvironment();
代码语言:javascript
复制
  11:      CreateHostBuilderContext();
代码语言:javascript
复制
  12:      BuildAppConfiguration();
代码语言:javascript
复制
  13:      CreateServiceProvider();
代码语言:javascript
复制
  14:   
代码语言:javascript
复制
  15:      return _appServices.GetRequiredService<IHost>();
代码语言:javascript
复制
  16:  }

该方法主要是包括以下功能:

创建HostingEnvironment

创建HostBuilderContext

配置初始化及格式标准化

DI(创建IHostEnvironment、IHostApplicationLifetime、IHostLifetime、IHost)

Run

Run方法运行应用程序并阻止调用线程,直到主机关闭

代码语言:javascript
复制
   1:  public static void Run(this IHost host)
代码语言:javascript
复制
   2:  {
代码语言:javascript
复制
   3:      host.RunAsync().GetAwaiter().GetResult();
代码语言:javascript
复制
   4:  }

以下是RunAsync的源码,此处可以通过设置CancellationToken的值,使应用程序自动关闭

代码语言:javascript
复制
   1:  public static async Task RunAsync(this IHost host, CancellationToken token = default)
代码语言:javascript
复制
   2:  {
代码语言:javascript
复制
   3:      try
代码语言:javascript
复制
   4:      {
代码语言:javascript
复制
   5:          await host.StartAsync(token);
代码语言:javascript
复制
   6:   
代码语言:javascript
复制
   7:          await host.WaitForShutdownAsync(token);
代码语言:javascript
复制
   8:      }
代码语言:javascript
复制
   9:      finally
代码语言:javascript
复制
  10:      {
代码语言:javascript
复制
  11:  #if DISPOSE_ASYNC
代码语言:javascript
复制
  12:          if (host is IAsyncDisposable asyncDisposable)
代码语言:javascript
复制
  13:          {
代码语言:javascript
复制
  14:              await asyncDisposable.DisposeAsync();
代码语言:javascript
复制
  15:          }
代码语言:javascript
复制
  16:          else
代码语言:javascript
复制
  17:  #endif
代码语言:javascript
复制
  18:          {
代码语言:javascript
复制
  19:              host.Dispose();
代码语言:javascript
复制
  20:          }
代码语言:javascript
复制
  21:   
代码语言:javascript
复制
  22:      }
代码语言:javascript
复制
  23:  }
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet技术平台 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • .NET Core 3.0中创建通用主机
    • CreateDefaultBuilder
      • Build
        • Run
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档