以上都是推论。那么直接看源码,因为是构建者模式,所以直接看build。
public IHost Build() { if (_hostBuilt) { throw new InvalidOperationException("Build can only be called once."); } _hostBuilt = true; BuildHostConfiguration(); CreateHostingEnvironment(); CreateHostBuilderContext(); BuildAppConfiguration(); CreateServiceProvider(); return _appServices.GetRequiredService<IHost>(); }上面的顺序和猜想是一致的。
这里看下BuildHostConfiguration:
private List<Action<IConfigurationBuilder>> _configureHostConfigActions = new List<Action<IConfigurationBuilder>>(); private void BuildHostConfiguration() { var configBuilder = new ConfigurationBuilder() .AddInMemoryCollection(); // Make sure there's some default storage since there are no default providers foreach (var buildAction in _configureHostConfigActions) { buildAction(configBuilder); } _hostConfiguration = configBuilder.Build(); }那么其实我们按照这种配置,那么其实我们的ConfigureHostConfiguration全部方法都是在_configureHostConfigActions 中,到了builder 的时候就按照我们的注册顺序执行。
那么这里就能解释ConfigureWebHostDefaults 不管顺序都是在最前面,而里面startup的顺序确不一样。
代码解释一波:
public static IHostBuilder ConfigureWebHostDefaults(this IHostBuilder builder, Action<IWebHostBuilder> configure) { return builder.ConfigureWebHost(webHostBuilder => { WebHost.ConfigureWebDefaults(webHostBuilder); configure(webHostBuilder); }); }ConfigureWebHostDefaults 立即执行,那么log自然就先打印出来了,而其他几个都是延迟执行的。他们的执行顺序和注册顺序有关。
最后再解释一下,webBuilder.UseStartup(); 到底做了什么?
public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType) { var startupAssemblyName = startupType.GetTypeInfo().Assembly.GetName().Name; hostBuilder.UseSetting(WebHostDefaults.ApplicationKey, startupAssemblyName); // Light up the GenericWebHostBuilder implementation if (hostBuilder is ISupportsStartup supportsStartup) { return supportsStartup.UseStartup(startupType); } return hostBuilder .ConfigureServices(services => { if (typeof(IStartup).GetTypeInfo().IsAssignableFrom(startupType.GetTypeInfo())) { services.AddSingleton(typeof(IStartup), startupType); } else { services.AddSingleton(typeof(IStartup), sp => { var hostingEnvironment = sp.GetRequiredService<IHostEnvironment>(); return new ConventionBasedStartup(StartupLoader.LoadMethods(sp, startupType, hostingEnvironment.EnvironmentName)); }); } }); }解释一下IsAssignableFrom:
bool res = {TypeA}.IsAssignableFrom({TypeB}) ; 如果TypeA和TypeB类型一样则返回true; 如果TypeA是TypeB的父类则返回true; 如果TypeB实现了接口TypeA则返回true;可以看到这里做的是一个IStartup 到 Startup的一个依赖注入,且是单例模式,所以肯定的是Startup 里面的方法会在ConfigureHostConfiguration、ConfigureAppConfiguration之后执行,因为其在ConfigureServices 才开始注入依赖的。
结因为是应用篇,单纯是一些应用需要知道的,所以比较粗糙,具体的详细在原理篇介绍了。上述只是个人的理解,如果错误,望请指点,谢谢。