从这里我们可以看出程序集信息来自于HostingStartupAssemblies属性,而且还要排除掉HostingStartupExcludeAssemblies包含的程序集。我们找到他们初始化的相关逻辑大致如下
//承载启动是需要调用的HostingStartup程序集 public IReadOnlyList<string> HostingStartupAssemblies { get; set; } //承载启动时排除掉不不要执行的程序集 public IReadOnlyList<string> HostingStartupExcludeAssemblies { get; set; } //是否阻止HostingStartup启动执行功能,如果设置为false则HostingStartup功能失效 //通过上面的ExecuteHostingStartups方法源码可知 public bool PreventHostingStartup { get; set; } //应用程序名称 public string ApplicationName { get; set; } public WebHostOptions(IConfiguration configuration, string applicationNameFallback) { ApplicationName = configuration[WebHostDefaults.ApplicationKey] ?? applicationNameFallback; HostingStartupAssemblies = Split($"{ApplicationName};{configuration[WebHostDefaults.HostingStartupAssembliesKey]}"); HostingStartupExcludeAssemblies = Split(configuration[WebHostDefaults.HostingStartupExcludeAssembliesKey]); PreventHostingStartup = WebHostUtilities.ParseBool(configuration, WebHostDefaults.PreventHostingStartupKey); } //分隔配置的程序集信息,分隔依据为";"分号,这也是我们上面说过配置多程序集的时候采用分号分隔的原因 private IReadOnlyList<string> Split(string value) { return value?.Split(';', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>(); }
首先,通过HostingStartupAssemblies的初始化逻辑我们可以得出,默认会是有两个数据来源,一个是当前的ApplicationName,另一个是通过HostingStartupAssembliesKey配置的程序集信息。这也解答了我们上面说过的为什么HostingStartup在Web程序中不需要配置程序集信息就可以被调用到,而通过外部程序集引入HostingStartup需要手动指定程序集。其次,我们可以了解到通过配置HostingStartupExcludeAssemblies信息排除你不想启动的HostingStartup程序集,而且还可以通过配置PreventHostingStartup值来禁止使用HostingStartup的功能。
通过上面的代码我们还了解到这三个属性的来源的配置名称都是来自WebHostDefaults这个常量类,接下来我们查看一下这三个属性对应的配置名称
public static readonly string HostingStartupAssembliesKey = "hostingStartupAssemblies"; public static readonly string HostingStartupExcludeAssembliesKey = "hostingStartupExcludeAssemblies"; public static readonly string PreventHostingStartupKey = "preventHostingStartup";
也就是说,我们可以可以通过配置这三个名称的配置,来完成HostingStartup相关的功能比如
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { //通过UseSetting的方式指定程序集的名称 webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "HostStartupLib"); //如果HostingStartup存在多个程序集中可以使用;分隔,比如HostStartupLib;HostStartupLib2 //webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "HostStartupLib;HostStartupLib2"); //排除执行HostStartupLib2程序集执行HostingStartup逻辑 webBuilder.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "HostStartupLib2"); //禁用HostingStartup功能 webBuilder.UseSetting(WebHostDefaults.PreventHostingStartupKey, "true"); webBuilder.UseStartup<Startup>(); });
或通过环境变量的方式去操作
"environmentVariables": { "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "HostStartupLib", //如果HostingStartup存在多个程序集中可以使用;分隔,比如HostStartupLib;HostStartupLib2 //"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "HostStartupLib;HostStartupLib2" //排除执行HostStartupLib2程序集执行HostingStartup逻辑 "ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES":"HostStartupLib2", //禁用HostingStartup功能 "ASPNETCORE_PREVENTHOSTINGSTARTUP":"true" }
其实这两种配置方式是完全等价的,为什么这么说呢?首先是在Configuration中获取配置是忽略大小写的,其实是使用ConfigureWebHostDefaults配置WebHost相关信息的时候会添加configBuilder.AddEnvironmentVariables(prefix: "ASPNETCORE_")逻辑这样的话获取环境变量的时候可以忽略ASPNETCORE_前缀。
那么到目前为止,还有一个疑问尚未解决,那就是为何只能通过UseSetting和环境变量的方式去配置HostingStartup相关配置,解铃还须系铃人,我们在上面的ExecuteHostingStartups方法中看到了这个逻辑
//这里传递了一个_config var webHostOptions = new WebHostOptions(_config, Assembly.GetEntryAssembly()?.GetName().Name);
我们可以看到传递了配置Configuration的实例_config,我们到初始化_config地方有如下逻辑