标签:
系列文章讲的是asp.net 5(Asp.net VNext)中的配置文件部分,工程下载地址为:https://github.com/aspnet/Configuration
本节讲的是Configuration解决方案中的Microsoft.Framework.Configuration和Microsoft.Framework.Configuration.Abstractions俩个工程。
Abstractions
首先我们看下Configuration.Abstractions这个工程的详情:

该工程中只定义了三个接口:IConfiguration、IConfigurationBuilder、IConfigurationSource,是完全为了抽象而设计的工程。
我们在依赖注入(DependencyInjection)篇中也接触过名字为“Abstractions”的工程(链接地址:http://www.cnblogs.com/watermoon2/p/4511269.html),也是只包含必须的接口定义,我们可以推测,微软的命名规则是对于XXXX类工程:
配置文件中,肯定少不了配置文件类的基础接口定义:IConfiguration;我们知道新的配置文件实现,支持配置文件有多个来源,可以来自xml、可以来自json、也可以既有部分来自xml,又有部分来自json,所以接口中定义了“IConfigurationSource”接口,用于标示配置文件的来源;而IConfigurationBuilder是IConfiguration的构造器。
这个工程代码比较少,下面我就将接口定义罗列如下:
接口定义Configuration
我们还是将工程的详情列出:

工程中一共八个cs文件:
1,IConfigurationSource实现类:ConfigurationSource、MemoryConfigurationSource
2,IConfigurationBuilder实现类:ConfigurationBuilder;IConfigurationBuilder扩展方法:ConfigurationHelper
3,IConfiguration实现类:ConfigurationSection、ConfigurationFocus
4,帮助辅助类:ConfigurationKeyComparer、Constants。
一个约定:":"
我们知道配置文件不都是线性的,可能有层次结构(比如传统的配置文件、json的、xml的)。我们读取配置文件的key值就需要有一定的逻辑。现在的逻辑是:
所以对于如下的json格式{"root1":"r1","root2":{"sub1":"s2"}},想要获取值是“s2”,所使用的key值是“root2:sub1”;“root2”是父节点的key,“:”是分隔符,“sub1”是当前key。
在这里的分隔符,其实就是定义在Constants类中,public static readonly string KeyDelimiter = ":"; 不过源文件中其他部分并未都直接使用该处定义,在IConfigurationSource的派生类也都是自己定义的“:”;所以想修改分隔符,在现有代码中不是能够只修改Constants中这个全局变量就可以的。所以在源码还有问题的时候,我们还是把分隔符=“:”,作为一个约定(不要试图把分隔符该城其他字符串)。
特殊的排序方式
由于当前key值得字符串可能是由存数字组成,我们希望key值为“1”,“2”,“10”的顺序是“1”,“2”,“10” 而不是“1”,“10”,“2”(字符串默认排序的顺序),所以系统在排序的时候使用了IComparer<string>接口。而IComparer<string>接口的实现类就是ConfigurationKeyComparer。
ConfigurationKeyComparer前面的铺垫已经讲完,下面我们进入正文:
ConfigurationBuilder以及ConfigurationHelper
ConfigurationBuilder的功能主要有四点:
代码中需要注意的也就只有一点:添加新的IConfigurationSource时,首先加载,之后再将IConfigurationSource对象添加到内部IConfigurationSource列表中。
ConfigurationHelper是ConfigurationBuilder的扩展,作用只有一个:
ConfigurationBuilder以及ConfigurationHelper源码如下:
ConfigurationBuilder
ConfigurationHelperConfigurationSource和MemoryConfigurationSource
ConfigurationSource实现了IConfigurationSource接口,是其他具体的IConfigurationSource父类,该类是抽象类,不能直接实例化。
该类主要提供以下几个功能:
MemoryConfigurationSource类继承自ConfigurationSource,提供了额外的方法:获取整个字典表。
[ConfigurationSource是扩展配置文件类型的基类,系统中就是通过继承自该类,实现xml以及json格式的配置文件类型]
ConfigurationSource
MemoryConfigurationSourceConfigurationSection和ConfigurationFocus
这两个类是双生类,使用了代理模式:通过GetConfigurationSection等获取IConfiguration方法返回的是ConfigurationFocus代理的ConfigurationSection(ConfigurationBuilder创建的是ConfigurationSection类)。简单的类关系图如下所示:(ConfigurationFocus不会和ConfigurationSource产生关联,会通过ConfigurationSection进行访问)

ConfigurationSection类实现的主要功能:
ConfigurationFocus实现的主要功能:
ConfigurationSection
ConfigurationFocus最后我们将ConfigurationSection和ConfigurationFocus的测试代码贴出,以便能够更好的理解俩个类的关系。
public void CanGetConfigurationSection()
{
// Arrange
var dic1 = new Dictionary<string, string>()
{
{"Data:DB1:Connection1", "MemVal1"},
{"Data:DB1:Connection2", "MemVal2"}
};
var dic2 = new Dictionary<string, string>()
{
{"DataSource:DB2:Connection", "MemVal3"}
};
var dic3 = new Dictionary<string, string>()
{
{"Data", "MemVal4"}
};
var memConfigSrc1 = new MemoryConfigurationSource(dic1);
var memConfigSrc2 = new MemoryConfigurationSource(dic2);
var memConfigSrc3 = new MemoryConfigurationSource(dic3);
var builder = new ConfigurationBuilder();
builder.Add(memConfigSrc1, load: false);
builder.Add(memConfigSrc2, load: false);
builder.Add(memConfigSrc3, load: false);
var config = builder.Build();
string memVal1, memVal2, memVal3, memVal4, memVal5;
bool memRet1, memRet2, memRet3, memRet4, memRet5;
// Act
var configFocus = config.GetConfigurationSection("Data");
memRet1 = configFocus.TryGet("DB1:Connection1", out memVal1);
memRet2 = configFocus.TryGet("DB1:Connection2", out memVal2);
memRet3 = configFocus.TryGet("DB2:Connection", out memVal3);
memRet4 = configFocus.TryGet("Source:DB2:Connection", out memVal4);
memRet5 = configFocus.TryGet(null, out memVal5);
// Assert
Assert.True(memRet1);
Assert.True(memRet2);
Assert.False(memRet3);
Assert.False(memRet4);
Assert.True(memRet5);
Assert.Equal("MemVal1", memVal1);
Assert.Equal("MemVal2", memVal2);
Assert.Equal("MemVal4", memVal5);
Assert.Equal("MemVal1", configFocus.Get("DB1:Connection1"));
Assert.Equal("MemVal2", configFocus.Get("DB1:Connection2"));
Assert.Null(configFocus.Get("DB2:Connection"));
Assert.Null(configFocus.Get("Source:DB2:Connection"));
Assert.Equal("MemVal4", configFocus.Get(null));
Assert.Equal("MemVal1", configFocus["DB1:Connection1"]);
Assert.Equal("MemVal2", configFocus["DB1:Connection2"]);
Assert.Null(configFocus["DB2:Connection"]);
Assert.Null(configFocus["Source:DB2:Connection"]);
Assert.Equal("MemVal4", configFocus[null]);
}
标签:
原文地址:http://www.cnblogs.com/Leo_wl/p/4532394.html