.Net Core下如何管理配置文件

1、前言

根據該issues來看,System.Configuration在.net core中已經不存在了,那麼取而代之的是由Microsoft.Extensions.Cnfiguration.XXX一系列的類庫提供,對應的開源地址爲點擊這裏git

 

從當前開源的代碼來看,在.net core下提供瞭如下類庫給咱們:github

Microsoft.Extensions.Configuration.Abstractions:基礎接口json

Microsoft.Extensions.Configuration:實現上面的基礎接口ide

Microsoft.Extensions.Configuration.FileProviderExtensions:提供重載配置擴展函數

Microsoft.Extensions.Configuration.Binder:提供轉換到實體功能工具

Microsoft.Extensions.Configuration.FileExtensions:提供配置文件根路徑擴展單元測試

 

如下爲提供對哪些方式的支持:學習

Microsoft.Extensions.Configuration.CommandLine:命令行參數開發工具

Microsoft.Extensions.Configuration.EnvironmentVariables:環境變量測試

Microsoft.Extensions.Configuration.Ini:Ini格式

Microsoft.Extensions.Configuration.Json:Json格式

Microsoft.Extensions.Configuration.Xml:Xml格式

 

由上面類庫的數量咱們能夠看出從此咱們不會在須要加載更多的庫,只要按需加載就能夠了,那麼咱們也能夠看到新的Configuration提供了更多格式的支持,固然咱們本身也能夠自行擴展以提供對更多格式的支持。下面咱們開始進入正文,從頭至尾的學習這5種支持的配置格式。

 

注意:須要VS2015開發工具

 

2、正文

首先咱們須要建立一個名爲「CoreClrConfiguration」的空解決方案,下面將會在這一個解決方案中將下面幾節的內容進行演示。若是讀者只對其中某一個部分感興趣能夠直接翻閱到對應的內容下,每一個小節都是相互獨立的沒有對應關係。

 

應該新建哪一種項目模板以下圖所示:

 

A. CommandLine(命令行參數)

 

在新建項目(名爲「CommandLineCfg」)中的project.json中增長如下的依賴(具體版本請讀者根據實際狀況決定)

"Microsoft.Extensions.Configuration.CommandLine": "1.0.0-rc1-final",

"Microsoft.Extensions.Configuration.Binder": "1.0.0-rc1-final"

須要注意的是該依賴庫爲全局依賴庫,非dnx451或dnxcore50下的依賴庫。

 

注:在project.json指定完依賴庫以後須要右擊「引用」->「還原程序包」,以後的部分將再也不闡述。

 

 

首先咱們先舉一個簡單的例子,讀取一個參數的值。首先打開Program.cs文件在其中寫入如下的程序:

 1 public static void Main(string[] args)
 2 {
 3         var cmdLineConfig = new CommandLineConfigurationProvider(args);
 4         cmdLineConfig.Load();
 5 
 6         string value1 = null;
 7        cmdLineConfig.TryGet("key1", out value1);
 8 
 9         Console.WriteLine($"key1={value1}");
10 
11         Console.ReadKey();
12 }

 

這裏咱們能夠看到「CommandLineConfigurationProvider」的命名,後面咱們介紹的可以提供對其餘格式的支持都會以「xxxConfigurationProvider」來命名的,而且基類都是「ConfigurationProvider」。簡單的介紹完以後下面咱們須要開始運行該程序,咱們先打開該項目的屬性,輸入一些測試用的命令行參數:

 

固然咱們這裏只是使用了其中一種支持的格式,其餘支持的格式以下:

-Key1=Value1

--Key1=Value1

/Key1=Value1

--Key1 Value1

 

若是讀者,在應用程序參數中的後面重複寫了「/Key1 Value2」那麼程序中只會採用最後一個設置的值且不區分大小寫。

 

注:若是命令行參數只傳遞了key而沒有傳遞value那麼在load的時候就會拋出FormatException異常。

 

相似於咱們經常使用的ORM同樣,對於外部命令行傳入的參數,key咱們實際上是能夠本身作投影,將對應的key改成咱們所但願的key。好比上面的「key1」咱們就能夠在改成「key2」。而要作到這一效果只須要在建立CommandLineConfigurationProvider的時候利用第二個參數將咱們便可,好比下面咱們將會將「key1」改成」key2」:

public static void Main(string[] args)
{
       Dictionary<string, string> defaults = new Dictionary<string, string>
       {
                { "--Key1","key2" }
        };

        var cmdLineConfig = new CommandLineConfigurationProvider(args, defaults);
        cmdLineConfig.Load();

        string value1 = null;
        cmdLineConfig.TryGet("key2", out value1);
        Console.WriteLine($"key1&key2={value1}");
            
        Console.ReadKey();
}

 

其中咱們能夠看到defaults字典中的key必須加上「--」或「-」不然在調用構造函數時將會拋出ArgumentException異常。最終咱們能夠看到獲取值的時候是利用後來咱們投影以後的key的名稱去獲取而不是「key1」了。

 

除了經過上面這種方式獲取值以外,還提供了一個通用的模型綁定,可以將其餘的格式轉換爲POCO,這樣可以便於咱們更快速的開發,下面筆者將經過兩種方式來說述,首先是利用咱們當前已經建立好的Provider來進行Bind,其中POCO以下:

public class CommandLineArgs
{
    public string Key1 { get; set; }
}

 

 

Main方法的實現以下:

var cmdLineConfig = new CommandLineConfigurationProvider(args);
var builder = new ConfigurationBuilder();
builder.Add(cmdLineConfig);
var item = builder.Build().Get<CommandLineArgs>();

Console.WriteLine($"key1&key2={item.Key1}");

其中ConfigurationBuilder能夠管理多個Provider,好比咱們開發一個系統能夠將命令行、Json文件、Ini文件和XML文件都添加到其中進行管理。若是咱們調用了Builder方法,那麼咱們就能夠利用其返回值統一的獲取咱們想要的值,內部會從這些Provider中嘗試獲取咱們須要的值若是有值則當即返回,而模型綁定是經過對其擴展加進去的。具體擴展瞭如下的方法:

public static class ConfigurationBinder
{
        public static void Bind(this IConfiguration configuration, object instance);
        public static object Get(this IConfiguration configuration, Type type);
        public static object Get(this IConfiguration configuration, Type type, string key);
        public static T Get<T>(this IConfiguration configuration);
        public static T Get<T>(this IConfiguration configuration, T defaultValue);
        public static T Get<T>(this IConfiguration configuration, string key);
        public static T Get<T>(this IConfiguration configuration, string key, T defaultValue);
}

 

其實如今Microsoft.Extensions.Configuration.Binder中。

 

另外一種方式則是不經過建立CommandLineConfigurationProvider直接利用ConfigurationBuilder實現相同的效果:

var builder = new ConfigurationBuilder();
builder.AddCommandLine(args);
var item = builder.Build().Get<CommandLineArgs>();
Console.WriteLine($"key1={item.Key1}");

其中AddCommandLine也是擴展方法,而且下面的四種中都有對應的擴展,內部的實現其實就是建立了Provider,好比這個方法的內部實現以下:

1 public static IConfigurationBuilder AddCommandLine(this IConfigurationBuilder configurationBuilder, string[] args)
2 {
3 configurationBuilder.Add(new CommandLineConfigurationProvider(args));
4 return configurationBuilder;
5 }

 

到這裏關於命令行參數告一段落,若是讀者想了解更多的信息,能夠查看對應的源碼以及單元測試。

 

B. EnvironmentVariables(環境變量)

在新建項目(名爲「EnvironmentVariablesCfg」)中的Project.json中增長如下的依賴:

"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-rc1-final",

"Microsoft.Extensions.Configuration.Binder": "1.0.0-rc1-final"

須要注意的是該依賴庫爲全局依賴庫,非dnx451或dnxcore50下的依賴庫。

 

跟以前的格式同樣,咱們這裏先經過一個簡單的例子來說述如何使用。相信不少新建過.NET Core項目的人都曾看到屬性窗口中的「環境變量」,可是殊不知道如何使用,而本節咱們將會利用它讀取對應的配置信息。首先咱們在其中新建一個值:

而後咱們打開Program.cs寫入如下的程序:

public static void Main(string[] args)
{
   var provider = new EnvironmentVariablesConfigurationProvider();
   provider.Load();

   string value = null;
   provider.TryGet("con", out value);
   Console.WriteLine($"con={value}");

   Console.ReadKey();
}

咱們能夠看到跟上一節的方式是如出一轍的,這樣對於咱們從此本身進行擴展來講,就避免的咱們系統內部的修改。

 

若是讀者細心查看provider中的Data會發現其中不只僅保存咱們的配置信息還保存了大量的系統配置信息,這是由於在調用Load的時候內部還將系統配置信息也讀取了,對應的源碼以下:

public override void Load()
{
   Load(Environment.GetEnvironmentVariables());
}

在咱們初始化provider時能夠看到構造函數還支持prefix,那麼下面咱們利用prefix來定義一個擁有本身前綴的配置避免跟其餘的配置信息相互衝突:

var provider = new EnvironmentVariablesConfigurationProvider("cfg:");
provider.Load();

string value = null;
provider.TryGet("con", out value);
Console.WriteLine($"con={value}");

Console.ReadKey();

讀者還要記獲得項目的屬性中將環境配置中的變量的key改爲cfg:Con,不然value獲取出來的就是null了。

 

相信聰明的讀者已經知道對應的如何使用了,因此筆者在這裏只列出對應的代碼(兩種方式)。

 public class EnvirVarCfg
 {
     public string Con { get; set; }
 }

 

 

方式1:

var provider = new EnvironmentVariablesConfigurationProvider("cfg:");
var builder = new ConfigurationBuilder();
builder.Add(provider);
var item = builder.Build().Get<EnvirVarCfg>();
Console.WriteLine($"con={item.Con}");

 

 

方式2:

var builder = new ConfigurationBuilder();
builder.AddEnvironmentVariables("cfg:");
var item = builder.Build().Get<EnvirVarCfg>();
Console.WriteLine($"con={item.Con}");

 

至此環境變量這節就結束了,若是已經掌握規律的讀者下面三節應該很快就可以掌握了。

 

C. Ini

在新建的項目(名爲「IniCfg」)中的Project.json中增長如下的依賴:

"Microsoft.Extensions.Configuration.Ini": "1.0.0-rc1-final",

"Microsoft.Extensions.Configuration.Binder": "1.0.0-rc1-final"

須要注意的是該依賴庫爲全局依賴庫,非dnx451或dnxcore50下的依賴庫。

 

首先咱們在項目根目錄下新建一個「config.ini」文件,並在其中寫入以下的內容以便咱們讀取:

[SegOne]
Con=localhost

[SegTwo]
Con=192.168.1.113
Ext:Port=5535

[Seg:Three]
Con=192.169.12.12

而後咱們打開Program.cs文件寫入以下代碼去讀取配置文件中的內容:

 1         public static void Main(string[] args)
 2         {
 3             string path = Path.Combine(Directory.GetCurrentDirectory(), "config.ini");
 4             var provider = new IniConfigurationProvider(path);
 5             provider.Load();
 6 
 7             string segoneCon = null;
 8             provider.TryGet("SegOne:Con", out segoneCon);
 9             Console.WriteLine($"SegOne-Con={segoneCon}");
10 
11             string segtwoCon = null;
12             provider.TryGet("SegTwo:Con", out segtwoCon);
13             Console.WriteLine($"SegTwo-Con={segtwoCon}");
14 
15             string segtwoExtPort = null;
16             provider.TryGet("SegTwo:Ext:Port", out segtwoExtPort);
17             Console.WriteLine($"SegTwo-Ext:Port={segtwoExtPort}");
18 
19             string segthreeCon = null;
20             provider.TryGet("Seg:Three:Con", out segthreeCon);
21             Console.WriteLine($"Seg:Three-Con={segthreeCon}");
22 
23             Console.ReadKey();
24         }
View Code

 

相同不少人都看見過相似的配置文件,特別是在搭建一些服務的時候,那麼從.net core開始也將原生支持這些配置,固然上面的示例中沒有給出對應的註釋,對應的註釋要以「;」、「#」和「/」開頭便可。

 

由於在該結構下會存在複雜類型包含複雜類型的狀況,因此下面咱們的模型可能比較複雜:

 1     public class IniModelCfg
 2     {
 3         public SegOne SegOne { get; set; }
 4         public SegTwo SegTwo { get; set; }
 5         public Seg Seg { get; set; }
 6     }
 7 
 8     public class SegOne
 9     {
10         public string Con { get; set; }
11     }
12 
13     public class SegTwo
14     {
15         public string Con { get; set; }
16         public Ext Ext { get; set; }
17     }
18 
19     public class Ext
20     {
21         public string Port { get; set; }
22     }
23 
24     public class Seg
25     {
26         public Three Three { get; set; }
27     }
28 
29     public class Three
30     {
31         public string Con { get; set; }
32     }
View Code

 

 

第一種實現方式:

            string path = Path.Combine(Directory.GetCurrentDirectory(), "config.ini");
            var provider = new IniConfigurationProvider(path);
            var builder = new ConfigurationBuilder();
            builder.Add(provider);
            var item = builder.Build().Get<IniModelCfg>();

            Console.WriteLine($"SegOne-Con={item.SegOne.Con}");
            Console.WriteLine($"SegTwo-Con={item.SegTwo.Con}");
            Console.WriteLine($"SegTwo-Ext:Port={item.SegTwo.Ext.Port}");
            Console.WriteLine($"Seg:Three-Con={item.Seg.Three.Con}");

 

 

第二種實現方式:

            string path = Path.Combine(Directory.GetCurrentDirectory(), "config.ini");
            var builder = new ConfigurationBuilder();
            builder.AddIniFile(path);
            var item = builder.Build().Get<IniModelCfg>();

            Console.WriteLine($"SegOne-Con={item.SegOne.Con}");
            Console.WriteLine($"SegTwo-Con={item.SegTwo.Con}");
            Console.WriteLine($"SegTwo-Ext:Port={item.SegTwo.Ext.Port}");
            Console.WriteLine($"Seg:Three-Con={item.Seg.Three.Con}");

 

 

D. Json

在新建的項目(名爲「JsonCfg」)中的Project.json中增長如下的依賴:

"Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final",

"Microsoft.Extensions.Configuration.Binder": "1.0.0-rc1-final"

須要注意的是該依賴庫爲全局依賴庫,非dnx451或dnxcore50下的依賴庫。

 

首先咱們在項目根目錄下新建一個「config.json」文件並在其中寫入以下的內容以便測試:

{
  "url": "localhost",
  "port": {
    "one": 1234,
    "two": 456
  }
}

 

而後打開Program.cs文件並在其中寫入以下內容:

            string path = Path.Combine(Directory.GetCurrentDirectory(), "config.json");
            var provider = new JsonConfigurationProvider(path);
            provider.Load();

            string url = null;
            provider.TryGet("url", out url);
            Console.WriteLine($"url={url}");

            string one = null;
            provider.TryGet("port:one", out one);
            Console.WriteLine($"port-one={one}");


            string two = null;
            provider.TryGet("port:two", out two);
            Console.WriteLine($"port0two={two}");

            Console.ReadKey();

如何獲取某個元素的元素跟Ini方式下是統一的,都是經過冒號來分割。

 

基本跟以前的仍是同樣的,筆者仍是會給出對應的代碼,首先是模型相關的代碼:

 1     public class JsonModelCfg
 2     {
 3         public string Url { get; set; }
 4         public Port Port { get; set; }
 5     }
 6 
 7     public class Port
 8     {
 9         public string One { get; set; }
10         public string Two { get; set; }
11     }
View Code

 

 

第一種實現方式:

            string path = Path.Combine(Directory.GetCurrentDirectory(), "config.json");
            var provider = new JsonConfigurationProvider(path);
            var builder = new ConfigurationBuilder();
            builder.Add(provider);
            var item = builder.Build().Get<JsonModelCfg>();

            Console.WriteLine($"url={item.Url}");
            Console.WriteLine($"port-one={item.Port.One}");
            Console.WriteLine($"port-two={item.Port.Two}");

 

 

第二種實現方式:

1             string path = Path.Combine(Directory.GetCurrentDirectory(), "config.json");
2             var builder = new ConfigurationBuilder();
3             builder.AddJsonFile(path);
4             var item = builder.Build().Get<JsonModelCfg>();
5 
6             Console.WriteLine($"url={item.Url}");
7             Console.WriteLine($"port-one={item.Port.One}");
8             Console.WriteLine($"port-two={item.Port.Two}");
View Code

 

 

E. Xml

在新建的項目(名爲「XmlCfg」)中的Project.json中增長如下的依賴:

"Microsoft.Extensions.Configuration.Xml": "1.0.0-rc1-final",

"Microsoft.Extensions.Configuration.Binder": "1.0.0-rc1-final"

須要注意的是該依賴庫爲全局依賴庫,非dnx451或dnxcore50下的依賴庫。

 

在項目根目錄下新建一個「config.xml」文件並在其中寫入以下內容以便後面的測試:

<settings>
  <data>
    <con>123456</con>
  </data>
  <inventory value="test" />
</settings>

而後打開Program.cs文件並在其中寫入以下代碼:

            string path = Path.Combine(Directory.GetCurrentDirectory(), "config.xml");
            var provider = new XmlConfigurationProvider(path);
            provider.Load();

            string con = null;
            provider.TryGet("data:con", out con);
            Console.WriteLine($"con={con}");

            string name = null;
            provider.TryGet("inventory:value", out name);
            Console.WriteLine($"value={name}");

            Console.ReadKey();

 

對應的模型綁定就再也不重複了,徹底如出一轍了。至此全部的配置相關的內容就介紹完畢了。

相關文章
相關標籤/搜索