.NET Core 3.0之深入源碼理解Host(一)


寫在前面

ASP .NET Core中的通用主機構建器是在v2.1中引入的,應用在啟動時構建主機,主機作為一個對象用於封裝應用資源以及應用程序啟動和生存期管理。其主要功能包括配置初始化(包括加載配置以及配置轉換為通用的鍵值對格式),創建托管環境和Host通用上下文、依賴注入等。

在.NET Core 3.0中采用了IHostBuilder用於創建Host,同時也不再建議使用Web主機,而建議使用泛型主機,主要原因是原有的通用主機僅適用於非HTTP負載,為了提供更加廣泛的主機方案,需要將HTTP管道與Web主機的接口分離出來。但Web主機仍會向后兼容。

host-update

.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:  }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM