ASP.NET Core : 二十三. 深入聊一聊配置的内部处理机制(二)

在Program文件的WebHost.CreateDefaultBuilder(args)方法中的ConfigureAppConfiguration方法被调用后,如果在CreateDefaultBuilder方法之后再次调用了ConfigureAppConfiguration方法并添加了数据源(如同上一节的例子),同样会生成相应的XXXConfigurationSource对象添加到ConfigurationBuilder的IList<IConfigurationSource> Sources集和中。


注意:这里不是每一种数据源生成一个XXXConfigurationSource,而是按照每次添加生成一个XXXConfigurationSource,并且遵循添加的先后顺序。例如添加多个JSON文件,会生成多个JsonConfigurationSource。


这些ConfigurationSource之间的关系如下图1:


ASP.NET Core : 二十三. 深入聊一聊配置的内部处理机制(二)图1


到这里各种数据源的收集工作完成,都添加到了ConfigurationBuilder的IList<IConfigurationSource> Sources属性中。


回到BuildCommonServices方法中,通过foreach循环逐一执行了configureAppConfiguration方法获取到IList<IConfigurationSource>之后,下一句是varconfiguration = builder.Build(),这是调用ConfigurationBuilder的Build()方法创建了一个IConfigurationRoot对象。对应代码如下:

public class ConfigurationBuilder : IConfigurationBuilder
    {
        public IList<IConfigurationSource> Sources { get; } = new List<IConfigurationSource>();
 
        //省略部分代码
 
        public IConfigurationRoot Build()
        {
            var providers = new List<IConfigurationProvider>();
            foreach (var source in Sources)
            {
                var provider = source.Build(this);
                providers.Add(provider);
            }
            return new ConfigurationRoot(providers);
        }
 
    }

这个方法主要体现了两个过程:首先,遍历IList<IConfigurationSource> Sources集合,主要调用其中的各个IConfigurationSource的Build方法创建对应的IConfigurationProvider,最终生成一个List<IConfigurationProvider>;第二,通过集合List<IConfigurationProvider>创建了ConfigurationRoot。ConfigurationRoot实现了IConfigurationRoot接口。


先看第一个过程,依然以JsonConfigurationSource为例,代码如下:

    public class JsonConfigurationSource : FileConfigurationSource
    {
        public override IConfigurationProvider Build(IConfigurationBuilder builder)
        {
            EnsureDefaults(builder);
            return new JsonConfigurationProvider(this);
        }
    }

JsonConfigurationSource会通过Build方法创建一个名为JsonConfigurationProvider的对象。通过JsonConfigurationProvider的名字可知,它是针对JSON类型的,也就是意味着不同类型的IConfigurationSource创建的IConfigurationProvider类型也是不一样的,对应图18‑4中的IConfigurationSource,生成的IConfigurationProvider关系如下图2。

ASP.NET Core : 二十三. 深入聊一聊配置的内部处理机制(二)图2


系统中添加的多个数据源被转换成了一个个对应的ConfigurationProvider,这些ConfigurationProvider组成了一个ConfigurationProvider的集合。


再看一下第二个过程,ConfigurationBuilder的Build方法的最后一句是return new ConfigurationRoot(providers),就是通过第一个过程创建的ConfigurationProvider的集合创建ConfigurationRoot。ConfigurationRoot代码如下:

public class ConfigurationRoot : IConfigurationRoot
    {
        private IList<IConfigurationProvider> _providers;
        private ConfigurationReloadToken _changeToken = new ConfigurationReloadToken();
 
        public ConfigurationRoot(IList<IConfigurationProvider> providers)
        {
            if (providers == null)
            {
                throw new ArgumentNullException(nameof(providers));
            }
 
            _providers = providers;
            foreach (var p in providers)
            {
                p.Load();
                ChangeToken.OnChange(() => p.GetReloadToken(), () => RaiseChanged());
            }
        }
//省略部分代码
}

可以看出,ConfigurationRoot的构造方法主要的作用就是将ConfigurationProvider的集合作为自己的一个属性的值,并遍历这个集合,逐一调用这些ConfigurationProvider的Load方法,并为ChangeToken的OnChange方法绑定数据源的改变通知和处理方法。


上一篇:CentOS自动同步互联网服务器时间


下一篇:Linux如何查看当前进程的ID