.net core 源码分析(6) 启动过程-InitializeAppConfiguration
InitializeAppConfiguration
方法用于初始化应用程序的配置。
private void InitializeAppConfiguration() { // 创建一个配置构建器,注意AddConfiguration(_hostConfiguration) IConfigurationBuilder configBuilder = new ConfigurationBuilder() //添加到共享属性 public IDictionary<string, object> Properties 中 .SetBasePath(_hostingEnvironment!.ContentRootPath) .AddConfiguration(_hostConfiguration!, shouldDisposeConfiguration: true); foreach (Action<HostBuilderContext, IConfigurationBuilder> buildAction in _configureAppConfigActions) { buildAction(_hostBuilderContext!, configBuilder); } // 私有属性赋值_appConfiguration ,注意和_hostConfigration区别 _appConfiguration = configBuilder.Build(); // 使用新的配置更新 HostBuilderContext,这里_hostBuilderContext.Configuration被覆盖了,覆盖之前指向_hostConfiguration _hostBuilderContext!.Configuration = _appConfiguration; }
在讲解整个过程之前有必要回顾一下Configuration模块中几个核心类型之间的关系。
ConfigurationBuilder.AddSource方法可以添加不同的配置源。 ConfigurationBuilder.AddConfiguration(_hostConfiguration) 其实就是把 _hostConfiguration 转换成为ChainedConfigurationSource类型的配置源。这样就实现了把_hostConfiguration的配置信息给合并到_appConfiguration中,所以即便_hostBuilderContext.Configuration被覆盖,但是还是可以通过新的对象访问到原有对象中的配置信息的。
/// <summary> /// 将一个现有的 <see cref="IConfiguration"/> 实例添加到指定的 /// <paramref name="configurationBuilder"/> 中,并可以选择在配置提供者被释放时自动释放配置对象。 /// </summary> /// <param name="configurationBuilder">要添加配置的 <see cref="IConfigurationBuilder"/>。</param> /// <param name="config">要添加的 <see cref="IConfiguration"/> 实例。</param> /// <param name="shouldDisposeConfiguration">指示在配置提供者被释放时,是否自动释放配置对象。</param> /// <returns>返回已修改的 <see cref="IConfigurationBuilder"/> 实例。</returns> public static IConfigurationBuilder AddConfiguration(this IConfigurationBuilder configurationBuilder, IConfiguration config, bool shouldDisposeConfiguration) { // 验证传入的参数不为 null ThrowHelper.ThrowIfNull(configurationBuilder); ThrowHelper.ThrowIfNull(config); // 将配置添加到构建器中,并指定是否需要在释放时释放配置对象 configurationBuilder.Add(new ChainedConfigurationSource { Configuration = config, ShouldDisposeConfiguration = shouldDisposeConfiguration, }); // 返回已修改的构建器 return configurationBuilder; }
最后附上ConfiguratonBuilder的源码
public class ConfigurationBuilder : IConfigurationBuilder { private readonly List<IConfigurationSource> _sources = new(); /// <summary> /// 返回用于获取配置值的配置源集合。 /// </summary> public IList<IConfigurationSource> Sources => _sources; /// <summary> /// 获取一个键/值集合 ///共享数据。 /// </summary> public IDictionary<string, object> Properties { get; } = new Dictionary<string, object>(); /// <summary> /// 添加一个新的配置源。 /// </summary> /// <param name="source">要添加的配置源。</param> /// <returns>返回当前的实例 <see cref="IConfigurationBuilder"/></returns> public IConfigurationBuilder Add(IConfigurationSource source) { ThrowHelper.ThrowIfNull(source); _sources.Add(source); return this; } public IConfigurationRoot Build() { var providers = new List<IConfigurationProvider>(); foreach (IConfigurationSource source in _sources) { IConfigurationProvider provider = source.Build(this); providers.Add(provider); } return new ConfigurationRoot(providers); } }
.net core 源码分析
有时候不是我们失去了目标,而是失去了方向。