DotNET Core 3.0 source-understanding Host (1)
Written in front
The generic host builder in ASP .NET Core was introduced in v2.1. The application builds the host at startup, and the host acts as an object for encapsulating application resources and application startup and lifetime management. Its main features include configuration initialization (including loading configuration and configuration conversion to a common key-value pair format), creating a managed environment and Host common context, dependency injection, and more.
In .NET Core 3.0, IHostBuilder is used to create Host, and Web Host is no longer recommended. It is recommended to use generic host. The main reason is that the original Universal Host is only suitable for non-HTTP load, in order to provide a wider range. The host solution needs to separate the HTTP pipe from the interface of the web host. But the web host will still be backward compatible.
Create a universal host in .NET Core 3.0
The following code is the template code provided in V3.0. You can see that in the process of creating the host, the way to create WebHostBuilder has been abandoned.
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: }
And in .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: }
The CreateHostBuilder() method provided in the V3.0 template looks very similar to CreateWebHostBuilder() in V2.X.
The main difference is that WebHost.CreateDefaultBuilder() is replaced by Host.CreateDefaultBuilder(). It is very easy to switch from v2.x to v3.0 using the CreateDefaultBuilder() helper method.
Another difference is the call to ConfigureWebHostDefaults(). Since the new host builder is a generic host builder, we must let it know that we are going to configure default settings for the web host. These default configurations can be implemented in the ConfigureWebHostDefaults() method.
CreateDefaultBuilder
The method Microsoft.Extensions.Hosting.Host, which is a static class, has two methods, one with the parameter CreateDefaultBuilder (string[] args), one is no parameter.
The no-parameter method source code is as follows,
1: public static IHostBuilder CreateDefaultBuilder() =>
2: CreateDefaultBuilder(args: null );
You can see that the method actually sets the default value.
The IHostBuilder CreateDefaultBuilder(string[] args) method has the following main functions:
Create a HostBuilder object
1: var builder = new HostBuilder();
Specify the content root directory to be used by Host
1: builder.UseContentRoot(Directory.GetCurrentDirectory());
Configuration initialization (environment variables, 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: })
Log
1: .ConfigureLogging((hostingContext, logging) =>
2: {
3: logging.AddConfiguration(hostingContext.Configuration.GetSection( "Logging" ));
4: logging.AddConsole();
5: logging.AddDebug();
6: logging.AddEventSourceLogger();
7: })
Enable scope validation in development environment mode
1: .UseDefaultServiceProvider((context, options) =>
2: {
3: var isDevelopment = context.HostingEnvironment.IsDevelopment();
4: options.ValidateScopes = isDevelopment;
5: options.ValidateOnBuild = isDevelopment;
6: });
Build
The Build() method is in Microsoft.Extensions.Hosting, and the method will only be executed once, of course, this time is only in the same instance.
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: }
The method mainly includes the following functions:
Create HostingEnvironment
Create a HostBuilderContext
Configuration initialization and format standardization
DI (create IHostEnvironment, IHostApplicationLifetime, IHostLifetime, IHost)
Run
The Run method runs the application and blocks the calling thread until the host closes
1: public static void Run( this IHost host)
2: {
3: host.RunAsync().GetAwaiter().GetResult();
4: }
The following is the source code of RunAsync, where the application can be automatically closed by setting the value of 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: }
twenty one:
22: }
23: }
Orignal link:https://www.cnblogs.com/edison0621/p/11025310.html