.Net Core Configuration源码探究 (2)

其实通过上面的代码我们会产生一个疑问,获取子节点数据返回的是另一个接口类型IConfigurationSection,我们来看下具体的定义

public interface IConfigurationSection : IConfiguration { string Key { get; } string Path { get; } string Value { get; set; } }

这个接口也是继承了IConfiguration,这就奇怪了分明只有一套配置IConfiguration,为什么还要区分IConfigurationRoot和IConfigurationSection呢?其实不难理解因为Configuration可以同时承载许多不同的配置源,而IConfigurationRoot正是表示承载所有配置信息的根节点,而配置又是可以表示层级化的一种结构,在根配置里获取下来的子节点是可以表示承载一套相关配置的另一套系统,所以单独使用IConfigurationSection去表示,会显得结构更清晰,比如我们有如下的json数据格式

{ "OrderId":"202005202220", "Address":"银河系太阳系火星", "Total":666.66, "Products":[ { "Id":1, "Name":"果子狸", "Price":66.6, "Detail":{ "Color":"棕色", "Weight":"1000g" } }, { "Id":2, "Name":"蝙蝠", "Price":55.5, "Detail":{ "Color":"黑色", "Weight":"200g" } } ] }

我们知道json是一个结构化的存储结构,其存储元素分为三种一是简单类型,二是对象类型,三是集合类型。但是字典是KV结构,并不存在结构化关系,在.Net Corez中配置系统是这么解决的,比如以上信息存储到字典中的结构就是这种

Key   Value  
OrderId   202005202220  
Address   银河系太阳系火星  
Products:0:Id   1  
Products:0:Name   果子狸  
Products:0:Detail:Color   棕色  
Products:1:Id   2  
Products:1:Name   蝙蝠  
Products:1:Detail:Weight   200g  
如果我想获取Products节点下的第一条商品数据直接 IConfigurationSection productSection = configuration.GetSection("Products:0")

类比到这里的话根配置IConfigurationRoot里存储了订单的所有数据,获取下来的子节点IConfigurationSection表示了订单里第一个商品的信息,而这个商品也是一个完整的描述商品信息的数据系统,所以这样可以更清晰的区分Configuration的结构,我们来看一下ConfigurationSection的大致实现

public class ConfigurationSection : IConfigurationSection { private readonly IConfigurationRoot _root; private readonly string _path; private string _key; public ConfigurationSection(IConfigurationRoot root, string path) { _root = root; _path = path; } public string Path => _path; public string Key { get { return _key; } } public string Value { get { return _root[Path]; } set { _root[Path] = value; } } public string this[string key] { get { //获取当前Section下的数据其实就是组合了Path和Key return _root[ConfigurationPath.Combine(Path, key)]; } set { _root[ConfigurationPath.Combine(Path, key)] = value; } } //获取当前节点下的某个子节点也是组合当前的Path和子节点的标识Key public IConfigurationSection GetSection(string key) => _root.GetSection(ConfigurationPath.Combine(Path, key)); //获取当前节点下的所有子节点其实就是在字典里获取包含当前Path字符串的所有Key public IEnumerable<IConfigurationSection> GetChildren() => _root.GetChildrenImplementation(Path); public IChangeToken GetReloadToken() => _root.GetReloadToken(); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspzdz.html