写在前面

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

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

.NET Core 3.0中创建通用主机

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

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

而在.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),一个是无参的。

无参方法源码如下,

   1:  public static IHostBuilder CreateDefaultBuilder() =>
   2:              CreateDefaultBuilder(args: null);

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

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

创建HostBuilder对象

   1:  var builder = new HostBuilder();

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

   1:  builder.UseContentRoot(Directory.GetCurrentDirectory());

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

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

日志

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

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

   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中,并且该方法只会执行一次,当然这种一次只是在同一个实例里面

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

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

创建HostingEnvironment

创建HostBuilderContext

配置初始化及格式标准化

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

Run

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

   1:  public static void Run(this IHost host)
   2:  {
   3:      host.RunAsync().GetAwaiter().GetResult();
   4:  }

以下是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:  }

.NET Core 3.0之深入源码理解Host(一)的更多相关文章

  1. .NET Core 3.0之深入源码理解Host(二)

      写在前面 停了近一个月的技术博客,随着正式脱离996的魔窟,接下来也正式恢复了.本文从源码角度进一步讨论.NET Core 3.0 中关于Host扩展的一些技术点,主要讨论Long Run Pro ...

  2. .NET Core 3.0之深入源码理解Startup的注册及运行

    原文:.NET Core 3.0之深入源码理解Startup的注册及运行   写在前面 开发.NET Core应用,直接映入眼帘的就是Startup类和Program类,它们是.NET Core应用程 ...

  3. .NET Core 3.0之深入源码理解Configuration(一)

    Configuration总体介绍 微软在.NET Core里设计出了全新的配置体系,并以非常灵活.可扩展的方式实现.从其源码来看,其运行机制大致是,根据其Source,创建一个Builder实例,并 ...

  4. .NET Core 3.0之深入源码理解Kestrel的集成与应用(一)

      写在前面 ASP.NET Core 的 Web 服务器默认采用Kestrel,这是一个基于libuv(一个跨平台的基于Node.js异步I/O库)的跨平台.轻量级的Web服务器. 在开始之前,先回 ...

  5. .NET Core 3.0之深入源码理解Kestrel的集成与应用(二)

      前言 前一篇文章主要介绍了.NET Core继承Kestrel的目的.运行方式以及相关的使用,接下来将进一步从源码角度探讨.NET Core 3.0中关于Kestrel的其他内容,该部分内容,我们 ...

  6. .NET Core 3.0之深入源码理解HttpClientFactory(二)

      写在前面 上一篇文章讨论了通过在ConfigureServices中调用services.AddHttpClient()方法,并基于此进一步探讨了DefaultHttpClientFactory是 ...

  7. .NET Core 3.0之深入源码理解ObjectPool(一)

    写在前面 对象池是一种比较常用的提高系统性能的软件设计模式,它维护了一系列相关对象列表的容器对象,这些对象可以随时重复使用,对象池节省了频繁创建对象的开销. 它使用取用/归还的操作模式,并重复执行这些 ...

  8. .NET Core 3.0之深入源码理解HealthCheck(一)

    写在前面 我们的系统可能因为正在部署.服务异常终止或者其他问题导致系统处于非健康状态,这个时候我们需要知道系统的健康状况,而健康检查可以帮助我们快速确定系统是否处于正常状态.一般情况下,我们会提供公开 ...

  9. .NET Core 3.0之深入源码理解Configuration(三)

      写在前面 上一篇文章讨论了文件型配置的基本内容,本篇内容讨论JSON型配置的实现方式,理解了这一种配置类型的实现方式,那么其他类型的配置实现方式基本可以触类旁通.看过了上一篇文章的朋友,应该看得出 ...

随机推荐

  1. python_网络编程

    网络ISO(国际标准化组织)--->网络体系结构标准(OSI模型)OSI: 网络信息传输比较复杂需要很多功能协同-->将功能分开,降低耦合度,让每个模块完成一定的功能-->将这些模块 ...

  2. block中self会造成循环引用问题

    将代码块中的 self换成unsafeSelf __unsafe_unretained 与 __weak 99%相同 __weak 当对象释放之后 会自动设置为nil 而__unsafe_unreta ...

  3. jQuery中带有异步Ajax代码的执行顺序

    1.问题 ​ 在使用jQuery的时候想通过Ajax请求来放所需要的html代码中放值,但是请求回来却是空的,源代码如下: $("a").click(function() { // ...

  4. 获取JVM转储文件的Java工具类

    在上期文章如何获取JVM堆转储文件中,介绍了几种方法获取JVM的转储文件,其中编程方法是里面唯一一个从JVM内部获取的方法.这里就不演示了其他方法获取正在运行的应用程序的堆转储,重点放在了使用编程来获 ...

  5. 有趣的css3实战案例剖析—(背景动态渐变)

    对于css3的学习,更多的是在于对新特性和基础理论的熟悉,这篇文章通过一个案例带领大家了解css3里一些理论知识,也将一些技巧加以总结,从而提高大家的开发效率: 本次案例为(背景颜色渐变),运用css ...

  6. 对于Python函数与方法,你可能存在些误解

    欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...

  7. 快速理解spark-on-k8s中的external-shuffle-service

    [摘要] external-shuffle-service是Spark里面一个重要的特性,有了它后,executor可以在不同的stage阶段动态改变数量,大大提升集群资源利用率.但是这个特性当前在k ...

  8. Springboot整合webservice

    Springboot整合webservice 2019-12-10 16:34:42 星期二 WebService是什么 WebService是一种跨编程语言和跨操作系统平台的远程调用技术,服务之间的 ...

  9. TCP 的三次握手,四次挥手和重要的细节—干货满满,建议细读

    最近把个人博客搭建好了,链接在这里:tobe的呓语,文章会先在博客和公众号更新~ 大家多多收藏啊 上一次讲了 UDP 协议,从这次开始,就要讲 TCP 协议了,因为 TCP 协议涉及到的东西很多,一篇 ...

  10. MyCat学习 ------分库分表 随笔

    垂直切分.水平切分 1.垂直分库,解决库中表太多的问题. 2.垂直分表,解决表中列太多的问题.例如 商品表 包含 产地.二维码 .时间.价格.各个列.分为不同的小表. 水平切分, 大数据表拆分为小表 ...