较之传统通过App.config和Web.config这两个XML文件承载的配置系统,ASP.NET Core采用的这个全新的配置模型的大一个优势是针对多种不同配置源的支持。我们可以将内存变量、命令行参数、环境变量和物理文件作为原始配置数据的来源,如果采用物理文件作为配置源,我们可以选择不同的格式,比如XML、JSON和INI等。如果这些默认支持的配置源形式还不能满足你的需求,我们还可以通过注册自定义ConfigurationProvider的方式将其他形式数据作为我们的配置来源。接下来让我们来逐个认识一下配置模型原生提供的ConfigurationProvider。
  目录
  MemoryConfigurationProvider
  EnvironmentVariablesConfigurationProvider
  CommandLineConfigurationProvider
  JsonConfigurationProvider
  XmlConfiguationProvider
  IniConfigurationProvider
  自定义ConfigurationProvider
  一、MemoryConfigurationProvider
  通过本章第2节对配置模型的介绍,我们知道ConfigurationProvider在配置模型中所起的作用是读取原始的配置数据并将其转换成基于数据字典的物理结构。在所有的ConfigurationProvider类型中,MemoryConfigurationProvider为简单直接,因为它对应的配置源是一个数据字典,根本不需要作任何的结构转换。
  MemoryConfigurationProvider定义在“Microsoft.Extensions.Configuration.Memory”命名空间下。。如下面的代码片段所示,派生于基类ConfigurationProvider的MemoryConfigurationProvider同时实现了IEnumerable<KeyValuePair<string, string>>接口,所以它自身可以作为一个字典对象来使用。原始的配置数据可以在创建MemoryConfigurationProvider的时候作为构造函数的参数来指定,也可以通过调用Add方法逐个进行添加。
  1: public class MemoryConfigurationProvider : ConfigurationProvider, IEnumerable<KeyValuePair<string, string>>
  2: {
  3:     public MemoryConfigurationProvider();
  4:     public MemoryConfigurationProvider(IEnumerable<KeyValuePair<string, string>> initialData);
  5:
  6:     public void Add(string key, string value);
  7:     public IEnumerator<KeyValuePair<string, string>> GetEnumerator();
  8: }
  在使用的时候,我们需要将MemoryConfigurationProvider对象注册到ConfigurationBuilder之上。具体来说,我们可以像前面演示的实例一样直接调用ConfigurationBuilder的Add方法,也可以调用如下所示的扩展方法AddInMemoryCollection。
  1: public static class MemoryConfigurationExtensions
  2: {
  3:     public static IConfigurationBuilder AddInMemoryCollection(this IConfigurationBuilder configurationBuilder);
  4:     public static IConfigurationBuilder AddInMemoryCollection(this IConfigurationBuilder configurationBuilder, IEnumerable<KeyValuePair<string, string>> initialData);
  5: }
  二、EnvironmentVariablesConfigurationProvider
  顾名思义,环境变量是描述当前执行环境并影响进程执行行为的变量。按照作用域的不同,我们将环境变量非常三类,它们分别针对当前系统、当前用户和当前进程。系统和用户级别的环境变量保存在注册表中,其路径分别为“HKEY_LOCAL_MACHINESYSTEMControlSet001ControlSession ManagerEnvironment”和“HKEY_CURRENT_USEREnvironment ”。
  环境变量提取和维护可以通过静态类型Environment来实现。具体来说,我们可以调用静态方法GetEnvironmentVariable方法获得某个指定名称的环境变量的值,而GetEnvironmentVariables方法则会将返回所有的环境变量,EnvironmentVariableTarget枚举类型的参数代表环境变量作用域决定的存储位置。如果在调用GetEnvironmentVariable或者GetEnvironmentVariables方法师没有显式指定target参数或者将此参数指定为EnvironmentVariableTarget.Process,在进程初始化前存在的所有环境变量(包括针对系统、当前用户和当前进程)将会作为候选列表。
1: public static class Environment
2: {
3:     public static string GetEnvironmentVariable(string variable);
4:     public static string GetEnvironmentVariable(string variable, EnvironmentVariableTarget target);
5:     public static IDictionary GetEnvironmentVariables();
6:     public static IDictionary GetEnvironmentVariables(EnvironmentVariableTarget target);
7:
8:     public static void SetEnvironmentVariable(string variable, string value);
9:     public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target);
10: }
11:
12: public enum EnvironmentVariableTarget
13: {
14:     Process,
15:     User,
16:     Machine
17: }
  环境变量的添加、修改和删除均由SetEnvironmentVariable方法来实现,如果没有显式指定target参数,默认采用的是EnvironmentVariableTarget.Process。如果希望删除指定名称的环境变量,我们只需要在调用这个方法的时候将value参数设置为Null或者空字符串即可。
  借助EnvironmentVariablesConfigurationProvider,我们可以将环境变量作为配置源。该类型定义在“Microsoft.Extensions.Configuration.EnvironmentVariables”程序集中,程序集的名称同时也是所在NuGet包的名称。如下面的代码片段所示,EnvironmentVariablesConfigurationProvider具有两个构造函数重载,如果调用默认无参构造函数,意味着我们会使用所有的环境变量。另一个构造函数提供了一个字符串类型的参数prefix,如果调用这个构造函数来创建一个EnvironmentVariablesConfigurationProvider,意味着我们只会使用名称以此为前缀的环境变量。
  1: public class EnvironmentVariablesConfigurationProvider : ConfigurationProvider
  2: {
  3:     public EnvironmentVariablesConfigurationProvider();
  4:     public EnvironmentVariablesConfigurationProvider(string prefix);
  5:     public override void Load();
  6: }
  由于作为原始配置数据的环境变量本身是一个Key和Value均为字符串的数据字典,所以EnvironmentVariablesConfigurationProvider无需在进行结构转换,所以当Load方法被执行之后,它只需要将符合条件筛选出来并添加到自己的配置字典中即可。有一点值得一提的是,如果我们在创建EnvironmentVariablesConfigurationProvider对象是指定了用于筛选环境变量的前缀,当符合条件的环境变量被添加到自身的配置字典之后,这个前缀也会从元素的Key中剔除。如下所示的代码片段基本上体现了EnvironmentVariablesConfigurationProvider的实现逻辑。
1: public class EnvironmentVariablesConfigurationProvider : ConfigurationProvider
2: {
3:     private readonly string prefix;
4:
5:     public EnvironmentVariablesConfigurationProvider(string prefix = null)
6:     {
7:         this.prefix = prefix ?? string.Empty;
8:     }
9:
10:     public override void Load()
11:     {
12:         var dictionary = Environment.GetEnvironmentVariables()
13:             .Cast<DictionaryEntry>()
14:             .Where(it => it.Key.ToString().StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
15:             .ToDictionary(it => it.Key.ToString().Substring(prefix.Length), it => it.Value.ToString());
16:         this.Data = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase);
17:    }
18: }