關于配置文件的目錄:[Asp.net 5] Configuration-新一代的配置文件
本系列文章講的是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.49028c.com/watermoon2/p/4511269.html),也是只包含必須的接口定義,我們可以推測,微軟的命名規則是對于XXXX類工程:
配置文件中,肯定少不了配置文件類的基礎接口定義:IConfiguration;我們知道新的配置文件實現,支持配置文件有多個來源,可以來自xml、可以來自json、也可以既有部分來自xml,又有部分來自json,所以接口中定義了“IConfigurationSource”接口,用于標示配置文件的來源;而IConfigurationBuilder是IConfiguration的構造器。
這個工程代碼比較少,下面我就將接口定義羅列如下:
public interface IConfigurationSource { bool TryGet(string key, out string value); void Set(string key, string value); void Load(); IEnumerable<string> PRoduceConfigurationSections( IEnumerable<string> earlierKeys, string prefix, string delimiter); } public interface IConfigurationBuilder { string BasePath { get; } IEnumerable<IConfigurationSource> Sources { get; } IConfigurationBuilder Add(IConfigurationSource configurationSource); IConfiguration Build(); }public interface IConfiguration { string this[string key] { get; set; } string Get(string key); bool TryGet(string key, out string value); IConfiguration GetConfigurationSection(string key); IEnumerable<KeyValuePair<string, IConfiguration>> GetConfigurationSections(); IEnumerable<KeyValuePair<string, IConfiguration>> GetConfigurationSections(string key); void Set(string key, string value); void Reload(); }接口定義
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。
public class ConfigurationKeyComparer : IComparer<string> { private const char Separator = ':'; public static ConfigurationKeyComparer Instance { get; } = new ConfigurationKeyComparer(); public int Compare(string x, string y) { var xParts = x?.Split(Separator) ?? new string[0]; var yParts = y?.Split(Separator) ?? new string[0]; // Compare each part until we get two parts that are not equal for (int i = 0; i < Math.Min(xParts.Length, yParts.Length); i++) { x = xParts[i]; y = yParts[i]; var value1 = 0; var value2 = 0; var xIsInt = x != null && int.TryParse(x, out value1); var yIsInt = y != null && int.TryParse(y, out value2); int result = 0; if (!xIsInt && !yIsInt) { // Both are strings result = string.Compare(x, y, StringComparison.OrdinalIgnoreCase); } else if (xIsInt && yIsInt) { // Both are int result = value1 - value2; } else { // Only one of them is int result = xIsInt ? -1 : 1; } if (result != 0) { // One of them is different return result; } } // If we get here, the common parts are equal. // If they are of the same length, then they are totally identical return xParts.Length - yParts.Length; } }ConfigurationKeyComparer
前面的鋪墊已經講完,下面我們進入正文:ConfigurationBuilder以及ConfigurationHelper
ConfigurationBuilder的功能主要有四點:
代碼中需要注意的也就只有一點:添加新的IConfigurationSource時,首先加載,之后再將IConfigurationSource對象添加到內部IConfigurationSource列表中。
ConfigurationHelper是ConfigurationBuilder的擴展,作用只有一個:
ConfigurationBuilder以及ConfigurationHelper源碼如下:
public class ConfigurationBuilder : IConfigurationBuilder { private readonly IList<IConfigurationSource> _sources = new List<IConfigurationSource>(); public ConfigurationBuilder(params IConfigurationSource[] sources) : this(null, sources) { } public ConfigurationBuilder(string basePath, params IConfigurationSource[] sources) { if (sources != null) { foreach (var singleSource in sources) { Add(singleSource); } } BasePath = basePath; } public IEnumerable<IConfigurationSource> Sources { ge
新聞熱點
疑難解答