ASP.NET Core的配置(6):多样性的配置来源[中篇]
作者:网络转载 发布时间:[ 2016/6/23 14:37:43 ] 推荐标签:配置管理 ASP.NET
ProfileDictionary.json
1: {
2: "profiles": {
3: "foo": {
4: "gender" : "Male",
5: "age" : "18",
6: "contactInfo": {
7: "email" : "foo@outlook.com",
8: "phoneNo" : "123"
9: }
10: },
11: "bar": {
12: "gender" : "Male",
13: "age" : "25",
14: "contactInfo": {
15: "email" : "bar@outlook.com",
16: "phoneNo" : "456"
17: }
18: },
19: "baz": {
20: "gender": "Female",
21: "age" : "40",
22: "contactInfo": {
23: "email" : "baz@outlook.com",
24: "phoneNo" : "789"
25: }
26: }
27: }
28: }
对于上面定义的三个JSON文件,我们可以按照如下的方式创建相应的JsonConfigurationProvider并注册到ConfigurationBuilder中。我们利用ConfigurationBuilder生成的Configuration对象,并采用配置绑定的方式得到对应的Profile、Profile[]和Dictionary<string,Profile>对象。
1: Profile profile = new ConfigurationBuilder()
2: .AddJsonFile("Profile.json")
3: .Build()
4: .Get<Profile>("Profile");
5:
6: Profile[] profileArray = new ConfigurationBuilder()
7: .AddJsonFile("ProfileCollection.json")
8: .Build()
9: .Get<Profile[]>("Profiles");
10:
11: Dictionary<string, Profile> profileDictionary = new ConfigurationBuilder()
12: .AddJsonFile("ProfileDictionary.json")
13: .Build()
14: .Get<Dictionary<string, Profile>>("Profiles");
二、XmlConfiguationProvider
XML也是一种常用的配置定义形式,它对数据的表达能力甚至强于JSON,基于所有类型的数据结构都可以通过XML表示出来。当我们通过一个XML元素表示一个复杂对象的时候,对象的数据成员定义成当前XML元素的子元素。如果数据成员是一个简单数据类型,我们还可以选择将其定义成当前XML元素的属性(Attribute)。针对一个Profile对象,我们可以采用如下两种不同的形式来定义。
1: <Profile>
2: <Gender>Male</Gender>
3: <Age>18</Age>
4: <ContactInfo>
5: <Email>foobar@outlook.com</Email>
6: <PhoneNo>123456789</PhoneNo>
7: </ContactInfo>
8: </Profile>
或者
1: <Profile Gender="Male" Age="18">
2: <ContactInfo Email="foobar@outlook.com" PhoneNo="123456789"/>
3: </Profile>
虽然XML对数据结构的表达能力总体要强于JSON,但是对于配置模型的一种数据来源却有自己的局限性,比如它们对集合的表现形式有点不尽如人意。举个简单的例子,对于一个元素类型为Profile的集合,我们可以采用具有如下结构的XML来表现。
1: <Profiles>
2: <Profile Gender="Male" Age="18">
3: <ContactInfo Email="foobar@outlook.com" PhoneNo="123"/>
4: </Profile>
5: <Profile Gender="Male" Age="25">
6: <ContactInfo Email="bar@outlook.com" PhoneNo="456"/>
7: </Profile>
8: <Profile Gender="Male" Age="40">
9: <ContactInfo Email="baz@outlook.com" PhoneNo="789"/>
10: </Profile>
11: </Profiles>
但是这段XML却不能正确地转换成配置字典,因为表示一个Profile对象的三个XML元素(<Profile>...</Profile>)是“同质”的,对于由它们表示的三个Profile对象来说,分别表示性别、年龄、电子邮箱地址和电话号码的四个叶子节点的路径是完全一样的,所以根据无法作为配置字典的Key。通过前面的介绍我们知道,如果需要通过配置字典来表示一个Profile对象的集合,我们需要按照如下的方式将集合元素的索引(0、1、2、…)作为路径的一部分。
1: 0:Gender
2: 0:Age
3: 0:ContactInfo:Email
4: 0:ContactInfo:PhoneNo
5:
6: 1:Gender
7: 1:Age
8: 1:ContactInfo:Email
9: 1:ContactInfo:PhoneNo
10:
11: 2:Gender
12: 2:Age
13: 2:ContactInfo:Email
14: 2:ContactInfo:PhoneNo
微软提供了一个不太理想方案来解决这个问题,那是在表示集合元素的XML元素中添加一个名为Name(不区分大小写)的属性。如果一个XML元素具有一个名为Name的特性,当它被转换成配置字典的时候,其属性和子元素对应的路径会自动将这个属性值作为前缀。比如我们在<ContactInfo>元素中按照如下的方式添加了一个值为“Foobar”的Name属性,Email和PhoneNo在配置字典中的Key将具有额外的前缀“Foobar”。
1: <ContactInfo Name="Foobar" Email="foobar@outlook.com" PhoneNo="123"/>
2:
3: Keys:
4: ContactInfo:Foobar:Email
5: ContactInfo:Foobar:PhoneNo
为了以XML的方式表示一个Profile集合,我们可以按照如下的方式在<Profile>元素上添加一个Name属性,并采用元素索引作为该属性的值。我之所以觉得这是一种不算理想的解决方案,只要源于两个因素:其一,直接赋予名为“Name”(不包含命名空间)的XML属性特殊的语义和行为是不合理的,假如Profile同样具有一个Name属性(这个属性实在太常见了),我们将不能用XML属性来表示它;其二,对于由这段XML生成的Configuration,表示Profile集合的路径是“Profiles:Profile”而不是“Profiles”,是否觉得很奇怪。
1: <Profiles>
2: <Profile Name="0" Gender="Male" Age="18">
3: <ContactInfo Email="foobar@outlook.com" PhoneNo="123"/>
4: </Profile>
5: <Profile Name="1" Gender="Male" Age="25">
6: <ContactInfo Email="bar@outlook.com" PhoneNo="456"/>
7: </Profile>
8: <Profile Name="2" Gender="Male" Age="40">
9: <ContactInfo Email="baz@outlook.com" PhoneNo="789"/>
10: </Profile>
11: </Profiles>
既然这个特性的XML属性具有自动附加前缀的作用,我们可以利用来表示集合元素的索引,如果需要使用XML来表示一个字典,我们照样可以用它来表示字典元素的Key。上面这段XML同样可以表示一个Dictionary<string, Profile>(或者Dictionary<int, Profile>)对象,字典元素的Key分别是“0”、“1”和“2”。不过,我们也可以采用如下所示的另一种方式表示一个Dictionary<string, Profile>对象。
1: <Profiles>
2: <Foo Gender="Male" Age="18">
3: <ContactInfo Email="foobar@outlook.com" PhoneNo="123"/>
4: </Foo>
5: <Bar Gender="Male" Age="25">
6: <ContactInfo Email="foobar@outlook.com" PhoneNo="123"/>
7: </Bar>
8: <Baz Gender="Male" Age="18">
9: <ContactInfo Email="baz@outlook.com" PhoneNo="789"/>
10: </Baz>
11: </Profiles>
针对XML文件的ConfigurationProvider类型为XmlConfigurationProvider,它定义在程序集“Microsoft.Extensions.Configuration.Xml”,这同样也是所在NuGet包的名称。因为同为针对文件的ConfigurationProvider,所以XmlConfigurationProvider具有与JsonConfigurationProvider完全一致的定义。除此之外,我们同样可以调用相应的扩展方法AddXmlFile根据指定的文件路径创建出相应的XmlConfigurationProvider对象并将其注册到指定的ConfigurationBuilder对象上。
1: public class XmlConfigurationProvider : ConfigurationProvider
2: {
3: public XmlConfigurationProvider (string path);
4: public XmlConfigurationProvider (string path, bool optional);
5:
6: public override void Load();
7:
8: public string Path { get; }
9: public bool Optional { get; }
10: }
11:
12: public static class XmlConfigurationExtensions
13: {
14: public static IConfigurationBuilder AddXmlFile(this IConfigurationBuilder configurationBuilder, string path);
15: public static IConfigurationBuilder AddXmlFile(this IConfigurationBuilder configurationBuilder, string path, bool optional);
16: }
三、IniConfigurationProvider
“INI”是“Initialization”的缩写,INI文件又被称为初始化文件,它是Windows系统普遍使用的配置文件,同时也被一些Linux和Unix系统所支持。INI文件直接以键值对的形式定义配置项,如下所示的代码片段体现了INI文件的基本格式。总的来说,INI文件以单纯的“{Key}={Value}”的形式定义配置项,{Value}可以定义在可选的双引号中(如果值的前后包括空白字符,必须使用双引号,否则会被忽略)。
1: [Section]
2: key1=value1
3: key2 = " value2 "
4: ; comment
5: # comment
6: / comment
除了以“{Key}={Value}”的定义的原子配置项外,我们还可以采用“[{SectionName}]”的形式定义配置节对它们进行分组。中括号(“[]”)同时作为下一个的配置节开始的标志,同时也作为上一个配置结束的标志,所以采用INI文件定义的配置节并不存在层次化的结构,即没有“子配置节”的概念。除此之外,我们可以在INI中定义相应的注释,注释行前置的字符可以采用“;”、“#”或者“/”。
由于INI文件自身体现为一个数据字典,所以我们可以采用“路径化”的Key来定义终绑定为复杂对象、集合或者字典的配置数据。如果采用INI文件来定义一个Profile对象的基本信息,我们可以采用如下定义形式。
1: Gender = "Male"
2: Age = "18"
3: ContactInfo:Email = "foobar@outlook.com"
4: ContactInfo:PhoneNo = "123456789"
有Profile的配置信息具有两个层次(Profile>ContactInfo),我们可以按照如下的形式将Emil和PhoneNo定义在配置节“ContactInfo”中,这个INI文件和上面是完全等效的。
1: Gender = "Male"
2: Age = "18"
3:
4: [ContactInfo]
5: Email = "foobar@outlook.com"
6: PhoneNo = "123456789"
作为针对INI文件的ConfigurationProvider,IniConfigurationProvider定义在程序集(同时也是NuGet包)“Microsoft.Extensions.Configuration.Ini”中。如下面的代码片断所示,IniConfigurationProvider和前面两个同是基于文件的ConfigurationProvider的定义完全一致。ConfigurationBuilder同样一个用于注册IniConfigurationProvider的扩展方法AddIniFile。
1: public class IniConfigurationProvider : ConfigurationProvider
2: {
3: public IniConfigurationProvider (string path);
4: public IniConfigurationProvider (string path, bool optional);
5:
6: public override void Load();
7:
8: public string Path { get; }
9: public bool Optional { get; }
10: }
11:
12: public static class IniConfigurationExtensions
13: {
14: public static IConfigurationBuilder AddIniFile(this IConfigurationBuilder configurationBuilder, string path);
15: public static IConfigurationBuilder AddIniFile (this IConfigurationBuilder configurationBuilder, string path, bool optional);
16: }
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南