我们在本篇文章中会介绍三种针对物理文件的ConfiguationProvider,它们分别是针对JSON文件的JsonConfiguationProvider,针对XML文件的XmlConfiguationProvider以及针对INI文件的IniConfiguationProvider。对于这三种文件类型(JSON、XML和INI)来说,JSON能够采用简单直观的格式表示具有不同结构的数据,所以它是作为配置最好的选择。

目录
MemoryConfigurationProvider
EnvironmentVariablesConfigurationProvider
CommandLineConfigurationProvider
JsonConfigurationProvider
XmlConfiguationProvider
IniConfigurationProvider
自定义ConfigurationProvider

一、JsonConfiguationProvider

我们可以将配置定义在一个JSON文件中,最终利用JsonConfiguationProvider加载该文件并将以JSON格式表示的配置原始数据转换成配置字典供配置模型使用。JsonConfiguationProvider定义在“Microsoft.Extensions.Configuration.Json”程序集下,它同样也是所在NuGet包的名称。

   1: public class JsonConfigurationProvider : ConfigurationProvider

   2: {

   3:     public JsonConfigurationProvider(string path);

   4:     public JsonConfigurationProvider(string path, bool optional);

   5:  

   6:     public override void Load();    

   7:    

   8:     public string    Path { get; }

   9:     public bool      Optional { get; }

  10: }

如上面的代码片断所示,JsonConfiguationProvider具有两个只读属性(Path和Optional),前者代表承载原始配置数据的JSON文件所在路径,后者表明当前的JsonConfiguationProvider是否是可选的ConfigurationProvider,其默认值为False。如果Optional为True,在创建JsonConfiguationProvider是指定一个不存在的文件将不会抛出异常,在这种情况下它会创建一个空的字典对象作为配置源。

在使用JsonConfiguationProvider的时候,我们可以直接创建这个对象并调用Add方法将其添加到指定的ConfigurationBuilder之中。我们可以直接调用ConfigurationBuilder对象具有如下定义的两个扩展方法AddJsonFile达到相同的目的。

   1: public static class JsonConfigurationExtensions

   2: {

   3:     public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder configurationBuilder, string path);

   4:     public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder configurationBuilder, string path, bool optional);

   5: }

当使用JSON文件来定义配置的时候,我们会发现不论对于何种数据结构(复杂对象、集合户者字典),我们都能通过JSON格式以一种简单而自然的方式来定义它们。同样以前面定义的Profile类型为例,我们可以利用如下所示的三个JSON文件分别定义一个完整的Profile对象、一个Profile对象的集合以及一个Key和Value类型分别为字符串和Profile的字典。

Profile.json

   1: {

   2:   "profile": {

   3:     "gender"  : "Male",

   4:     "age"     : "18",

   5:     "contactInfo": {

   6:       "email"        : "foobar@outlook.com",

   7:       "phoneNo"      : "123456789"

   8:     }

   9:   }

  10: }

ProfileCollection.json

   1: {

   2:   "profiles": [

   3:     {

   4:       "gender"       : "Male",

   5:       "age"          : "18",

   6:       "contactInfo": {

   7:         "email"      : "foo@outlook.com",

   8:         "phoneNo"    : "123"

   9:       }

  10:     },

  11:     {

  12:       "gender" : "Male",

  13:       "age"   : "25",

  14:       "contactInfo": {

  15:         "email"      : "bar@outlook.com",

  16:         "phoneNo"    : "456"

  17:       }

  18:     },

  19:     {

  20:       "gender" : "Female",

  21:       "age"   : "40",

  22:       "contactInfo": {

  23:         "email"      : "baz@outlook.com",

  24:         "phoneNo"    : "789"

  25:       }

  26:     }

  27:   ]

  28: }

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: }

ASP.NET Core的配置(1):读取配置信息
ASP.NET Core的配置(2):配置模型详解
ASP.NET Core的配置(3): 将配置绑定为对象[上篇]
ASP.NET Core的配置(3): 将配置绑定为对象[下篇]
ASP.NET Core的配置(4):多样性的配置源[上篇]
ASP.NET Core的配置(4):多样性的配置源[中篇]
ASP.NET Core的配置(4):多样性的配置源[下篇]
ASP.NET Core的配置(5):配置的同步[上篇]
ASP.NET Core的配置(5):配置的同步[下篇]

ASP.NET Core的配置(4):多样性的配置来源[中篇]的更多相关文章

  1. ASP.NET Core 2.2 基础知识(六) 配置(内含MySql+EF)

    先上一段代码,了解一下 .NET Core 配置数据的结构. 新建一个 控制台项目,添加一个文件 json.json ,文件内容如下: { "country": "cn& ...

  2. asp.net core 3.0 MVC JSON 全局配置

    asp.net core 3.0 MVC JSON 全局配置 System.Text.Json(default) startup配置代码如下: using System.Text.Encodings. ...

  3. [ASP.NET Core 3框架揭秘] Options[1]: 配置选项的正确使用方式[上篇]

    依赖注入不仅是支撑整个ASP.NET Core框架的基石,也是开发ASP.NET Core应用采用的基本编程模式,所以依赖注入十分重要.依赖注入使我们可以将依赖的功能定义成服务,最终以一种松耦合的形式 ...

  4. [ASP.NET Core 3框架揭秘] Options[2]: 配置选项的正确使用方式[下篇]

    四.直接初始化Options对象 前面演示的几个实例具有一个共同的特征,即都采用配置系统来提供绑定Options对象的原始数据,实际上,Options框架具有一个完全独立的模型,可以称为Options ...

  5. [ASP.NET Core开发实战]基础篇06 配置

    配置,是应用程序很重要的组成部分,常常用于提供信息,像第三方应用登录钥匙.上传格式与大小限制等等. ASP.NET Core提供一系列配置提供程序读取配置文件或配置项信息. ASP.NET Core项 ...

  6. [ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [中篇]

    我们在<上篇>利用dotnet new命令创建了一个简单的控制台程序,接下来我们将它改造成一个ASP.NET Core应用.一个ASP.NET Core应用构建在ASP.NET Core框 ...

  7. [转][ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [中篇]

    我们在<上篇>利用dotnet new命令创建了一个简单的控制台程序,接下来我们将它改造成一个ASP.NET Core应用.一个ASP.NET Core应用构建在ASP.NET Core框 ...

  8. ASP.NET Core 缓存技术 及 Nginx 缓存配置

    前言 在Asp.Net Core Nginx部署一文中,主要是讲述的如何利用Nginx来实现应用程序的部署,使用Nginx来部署主要有两大好处,第一是利用Nginx的负载均衡功能,第二是使用Nginx ...

  9. Asp.Net Core轻松入门之WebHost的配置

    在本篇文章中,我来讲一讲如何利用WebHost来加载配置文件和设置启动的Url 在前面的文章中讲过,ASP.Net Core应用程序会自动加载appsettings.json中的配置文件,那么如果配置 ...

  10. ASP.NET Core 从 gitlab-ci 环境变量读取配置

    最近在加强持续集成,遇到一个场景需要通过 gitlab-ci 环境变量(Settings -> Settings -> CI/CD -> Variables )在持续集成时向 ASP ...

随机推荐

  1. 第二章 Matlab面向对象编程基础

    DeepLab是一款基于Matlab面向对象编程的深度学习工具箱,所以了解Matlab面向对象编程的特点是必要的.笔者在做Matlab面向对象编程的时候发现无论是互联网上还是书店里卖的各式Matlab ...

  2. web优化 js性能高级篇

    今天我们继续上一个阶段关于web的性能优化,如何对js高级进行优化 (1)闭包 何为闭包; 一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.  我认 ...

  3. A library of generic data structures

    A library of generic data structures including a list, array, hashtable, deque etc.. https://github. ...

  4. ASIHTTPRequest取消异步请求

    今天碰到一个问题 异步请求等待中 cancel后会发生什么,网上找了下资料说取消的请求默认都会按请求失败处理,并调用请求失败delegate 查找到的资料具体解释了下ASIHTTPRequest取消异 ...

  5. 媒体查询(pc端,移动端不同布局)

    媒体查询语法: 1.内联写法:and之后必须有空格@media screen and (min-width:960px //判断浏览器大小条件){body{background:red} //常规的样 ...

  6. 【hihoCoder】1121:二分图一·二分图判定

      题目   http://hihocoder.com/problemset/problem/1121 无向图上有N个点,两两之间可以有连线,共有M条连线. 如果对所有点进行涂色(白/黑),判定是否存 ...

  7. web应用程序

    1.web应用程序和网站的区别 应用程序有两种模式C/S.B/S.C/S是客户端/服务器端程序,也就是说这类程序一般独立运行.而B/S就是浏览器端/服务器端应用程序,这类应用程序一般借助IE等浏览器来 ...

  8. centos6字符

    [root@back_zabbix_100 ~]# echo $LANGen_US.UTF-8[root@back_zabbix_100 ~]# cat /etc/sysconfig/i18n LAN ...

  9. IOS第二天-新浪微博 - 添加搜索框,弹出下拉菜单 ,代理的使用 ,HWTabBar.h(自定义TabBar)

    ********HWDiscoverViewController.m(发现) - (void)viewDidLoad { [super viewDidLoad]; // 创建搜索框对象 HWSearc ...

  10. Tomcat启动失败Unrecognized Windows Sockets error: 0: JVM_Bind

    问题:Tomcat一直无法运行,或者是运行了报上面图片的哪些错误. 解决:关闭myeclipse,打开任务管理器(Ctrl+Alt+Delete)关闭javaw.exe这个进程,另外说一下,Tomca ...