首先当我们创建.NET5 Web API 程序的时候,会生成下面这个 Program.cs 文件:
1public 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}
这个类包含两个方法:Main 和 CreateHostBuilder.
通过Host类调用CreateHostBuilder方法返回一个IHostBuilder对象,那么这个主机对象是什么呢?
Host类实现了IHost接口,用途如下:
-
应用程序配置设置
-
给应用程序添加依赖注入,配置.NET Core本机容器
-
配置日志
Host.cs
Host 是一个静态类,包含了两个方法: CreateDefaultBuilder() 、CreateDefaultBuilder (args)
在下面源码中我将会剖析这两个方法的用途:
1public static class Host
2 {
3 public static IHostBuilder CreateDefaultBuilder() =>
4 CreateDefaultBuilder(args: null);
5
6 public static IHostBuilder CreateDefaultBuilder(string[] args)
7 {
8 var builder = new HostBuilder();
9
10 builder.UseContentRoot(Directory.GetCurrentDirectory());
11 builder.ConfigureHostConfiguration(config =>
12 {
13 config.AddEnvironmentVariables(prefix: "DOTNET_");
14 if (args != null)
15 {
16 config.AddCommandLine(args);
17 }
18 });
19
20 builder.ConfigureAppConfiguration((hostingContext, config) =>
21 {
22 IHostEnvironment env = hostingContext.HostingEnvironment;
23
24 bool reloadOnChange = hostingContext.Configuration.GetValue("hostBuilder:reloadConfigOnChange", defaultValue: true);
25
26 config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: reloadOnChange)
27 .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: reloadOnChange);
28
29 if (env.IsDevelopment() && !string.IsNullOrEmpty(env.ApplicationName))
30 {
31 var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
32 if (appAssembly != null)
33 {
34 config.AddUserSecrets(appAssembly, optional: true);
35 }
36 }
37
38 config.AddEnvironmentVariables();
39
40 if (args != null)
41 {
42 config.AddCommandLine(args);
43 }
44 })
45 .ConfigureLogging((hostingContext, logging) =>
46 {
47 bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
48
49 if (isWindows)
50 {
51
52 logging.AddFilter<EventLogLoggerProvider>(level => level >= LogLevel.Warning);
53 }
54
55 logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
56 logging.AddConsole();
57 logging.AddDebug();
58 logging.AddEventSourceLogger();
59
60 if (isWindows)
61 {
62 logging.AddEventLog();
63 }
64
65 logging.Configure(options =>
66 {
67 options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
68 | ActivityTrackingOptions.TraceId
69 | ActivityTrackingOptions.ParentId;
70 });
71
72 })
73 .UseDefaultServiceProvider((context, options) =>
74 {
75 bool isDevelopment = context.HostingEnvironment.IsDevelopment();
76 options.ValidateScopes = isDevelopment;
77 options.ValidateOnBuild = isDevelopment;
78 });
79
80 return builder;
81 }
82 }
首先无参的CreateDefaultBuilder()方法只是通过调用传递null值来调用有参的CreateDefaultBuilder(string[] args)方法。
var builder = new HostBuilder();
CreateDefaultBuilder(string[] args) 方法从创建HostBuilder 类型对象的实例化开始(继承自IHostBuilder),我们可以直接在这个实例上调用Build.Run()方法来启动我们的ASP.NET 主机,但是只是这样调用的话,并没有对我们的主机以及应用程序做配置,那么怎么配置呢?
Host Configuration(主机配置)
1builder.UseContentRoot(Directory.GetCurrentDirectory());
这个方法定义了Host 执行的目录,默认是根目录。
应用程序配置(Setting up the app)
1builder.ConfigureAppConfiguration((hostingContext, config) =>
2{
3 IHostEnvironment env = hostingContext.HostingEnvironment;
4
5 bool reloadOnChange = hostingContext.Configuration.GetValue("hostBuilder:reloadConfigOnChange", defaultValue: true);
6
7 config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: reloadOnChange)
8 .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: reloadOnChange);
9
10 if (env.IsDevelopment() && !string.IsNullOrEmpty(env.ApplicationName))
11 {
12 var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
13 if (appAssembly != null)
14 {
15 config.AddUserSecrets(appAssembly, optional: true);
16 }
17 }
18
19 config.AddEnvironmentVariables();
20
21 if (args != null)
22 {
23 config.AddCommandLine(args);
24 }
25});
hostingContext.HostingEnvironment 表示我们在开发或者生产环境下的环境信息。
1bool reloadOnChange = hostingContext.Configuration.GetValue("hostBuilder:reloadConfigOnChange", defaultValue: true);
2
3config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: reloadOnChange)
4 .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: reloadOnChange);
在程序启动配置时,它会加载我们项目中的appsettings.json及其下面的配置json 文件。通过AddJsonFile()这个方法来实现,这个方法有三个入参:
-
Path(string): .json 文件的相对路径位置
-
Optional(bool): 指定文件是否是必须的,如果设置为false,那么如果找不到文件则会抛出文件找不到异常。
-
ReloadOnchange(bool): 如果设置为true,那么我们改变配置文件,那么应用程序也会随之更改而无需重新启动。
1bool reloadOnChange = hostingContext.Configuration.GetValue("hostBuilder:reloadConfigOnChange", defaultValue: true);
这段代码是.NET5 新增的,在之前.net core的应用程序中,reloadOnchange的值始终是ture,至此我们就可以对hostBuilder:reloadConfigOnChange 配置为false;
1if (env.IsDevelopment() && !string.IsNullOrEmpty(env.ApplicationName))
2{
3 var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
4 if (appAssembly != null)
5 {
6 config.AddUserSecrets(appAssembly, optional: true);
7 }
8}
这段程序的作用是如果我们需要加密我们的appsettings.json文件,则可以使用;用法如下:https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-3.1&tabs=windows
配置日志(Logging)
1.ConfigureLogging((hostingContext, logging) =>
2 {
3 bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
4
5 // IMPORTANT: This needs to be added *before* configuration is loaded, this lets
6 // the defaults be overridden by the configuration.
7 if (isWindows)
8 {
9 // Default the EventLogLoggerProvider to warning or above
10 logging.AddFilter<EventLogLoggerProvider>(level => level >= LogLevel.Warning);
11 }
12
13 logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
14 logging.AddConsole();
15 logging.AddDebug();
16 logging.AddEventSourceLogger();
17
18 if (isWindows)
19 {
20 // Add the EventLogLoggerProvider on windows machines
21 logging.AddEventLog();
22 }
23
24 logging.Configure(options =>
25 {
26 options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
27 | ActivityTrackingOptions.TraceId
28 | ActivityTrackingOptions.ParentId;
29 });
30 })
上述代码用来设置应用程序的生成日志;从代码中可以看出如果程序跑在windows环境下,级别是或者高于警告级别的日志将会被输出在控制台,VS输出窗口以及写入系统日志服务。
依赖注入
1.UseDefaultServiceProvider((context, options) =>
2{
3 bool isDevelopment = context.HostingEnvironment.IsDevelopment();
4 options.ValidateScopes = isDevelopment;
5 options.ValidateOnBuild = isDevelopment;
6});
CreateDefaultBuilder 方法的最后一步是将依赖注入添加到我们的应用程序中。UseDefaultServiceProvider这个方法用来添加.NET 5 或者.NET Core自带的IOC容器。