1. 程式人生 > >.NET平臺開源專案速覽(5)深入使用與擴充套件SharpConfig元件

.NET平臺開源專案速覽(5)深入使用與擴充套件SharpConfig元件

  上個月在文章:這些.NET開源專案你知道嗎?讓.NET開源來得更加猛烈些吧  和 .NET平臺開源專案速覽(1)SharpConfig配置檔案讀寫元件 中都提到了SharpConfig元件,簡單輕量級,速度快,而且還有比較深入的使用介紹。在文章釋出後,也有網友提到一些問題,當時我也沒仔細去分析,在這次我親自使用的過程中,就對幾個問題進行了比較深入的研究,同時對不滿足自己的地方,也進行了擴充套件。所以今天就把對SharpConfig的原始碼進行一個簡單的分析,同時也根據需求對自己的一個特殊情況進行擴充套件。自己動手豐衣足食。。。

1.SharpConfig原始碼分析

  SharpConfig原始碼並不大,核心程式碼其實也很簡單,就是檔案讀寫,解析。在深入使用和擴充套件SharpConfig之前,有必要了解一下它的基本結構。所以先來介紹SharpConfig原始碼中核心的3大類。

   Configuration是核心類,我們在前面的文章中只是簡單的介紹了一下如何載入配置檔案,檢視原始碼,可以發現載入和儲存的方法都是匹配的,都可以從檔案或者資料流中載入或者儲存。

blob.png

     由於每一個配置檔案都包含若干個Section節,所以也可以使用索引來獲取這些節,然後操作節下面的設定項。總的來說思路是很簡單的。  

  Configuration在解析過程中,每碰到一個Section,就新增到列表中。而Section的區分就是靠Name,所以,我們在配置檔案中注意不要把Section的名稱搞混淆了。Section原始碼中沒有特別需要注意的地方,主要是這裡檢測和移除節點的方法,如下面程式碼:

 1 /// <summary>檢測節中是否存在某個特定名稱的設定 </summary>
 2 /// <param name="settingName">設定項的名稱</param>
 3 /// <returns>True if the setting is contained in the section; false otherwise.</returns>
 4 public bool Contains(string settingName)
 5 {
 6     return GetSetting(settingName) != null
; 7 } 8 9 /// <summary>從本節中移除某個名稱的設定</summary> 10 public void Remove(string settingName) 11 { 12 if (string.IsNullOrEmpty(settingName)) 13 throw new ArgumentNullException("settingName"); 14 15 var setting = GetSetting(settingName); 16 17 if (setting == null) 18 { 19 throw new ArgumentException("The specified setting does not exist in the section."); 20 } 21 mSettings.Remove(setting); 22 }

  每一個Section下面可以有多個Setting設定。下面看看Setting類的情況。 Setting主要是獲取和設定值的方法,如程式碼:

var someInteger = section["SomeInteger"].GetValue<Boolean>();
float someFloat = section["SomeFloat"].GetValue<float>();

    什麼只是簡單的對SharpConfig 的結構做一個分析,下面我們將針對問題進行跟深入的分析和修改。

2.SharpConfig使用問題與擴充套件

2.1 讀取亂碼的問題

  第一次發現這個問題並不是我,是網友在看完我的文章介紹後使用,發現讀取出來是亂碼,不能解析。然後反饋給我。其實問題很簡單,只是我也沒有注意,其實讀取的時候也多個方法可以選擇, 預設使用的是null編碼設定,系統自動檢測,但這非常不保險。最好還是自己把檔案的編碼寫進去。例如:

Configuration config = Configuration.LoadFromFile("example.ini", Encoding.GetEncoding("gb2312"));

這樣修改後,如果配置檔案中有中文,一般是沒問題的。非常重要的一點,如果你讀取的時候用了固定編碼,修改配置值需要儲存的時候,也一定要加上編碼,否則會導致其他的配置都發生亂碼的情況。如下面的程式碼:

config.Save("example.ini", Encoding.GetEncoding("gb2312"));

  編碼的問題,我們可以看一下原始碼中的情況:

 1 /// <summary>從配置檔案直接載入,自動檢測編碼型別,以及使用預設的設定</summary>
 2 /// <param name="filename">本地配置檔名稱</param>
 3 public static Configuration LoadFromFile(string filename)
 4 {
 5     return LoadFromFile(filename, null);
 6 }
 7 
 8 /// <summary>從配置檔案直接載入</summary>
 9 /// <param name="filename">本地配置檔名稱</param>
10 /// <param name="encoding">檔案的編碼型別,如果為Null,則自動檢測</param>
11 public static Configuration LoadFromFile(string filename, Encoding encoding)
12 {
13     if (!File.Exists(filename))
14         throw new FileNotFoundException("Configuration file not found.", filename);
15 
16     Configuration cfg = null;
17 
18     if (encoding == null)
19         cfg = LoadFromText(File.ReadAllText(filename));
20     else
21         cfg = LoadFromText(File.ReadAllText(filename, encoding));
22 
23     return cfg;
24 }

2.2 需要賦空值的情況

  碰到這個問題,可能有些變態吧。其實並不是一個問題,如果需要是String,建議直接寫一個固定的值,在後臺讀取的時候進行判斷,因為SharpConfig處理的時候,會剔除前後的空白字元。所以這種情況你直接給空字串是不可取 的,給一個 null,然後後臺判斷是否==null,然後進行對應操作;如果是數值型別,也可以特定的設定一個值,比如為0,轉換 的時候 判斷是否為0,否則作為空處理。

2.3 #註釋符與字串衝突的問題

  在SharpConfig中,其實有一個可以定義註釋符的地方。

/// <summary>獲取或者設定 註釋標識字元</summary>
public static char[] ValidCommentChars
{
    get { return mValidCommentChars; }
    set
    {
        if (value == null) throw new ArgumentNullException("value");
        if (value.Length == 0)
        {
            throw new ArgumentException("The comment chars array must not be empty.","value");
        }
        mValidCommentChars = value;
    }
}

  在配置類的靜態建構函式中,預設給了這幾個字元作為識別符號:

//靜態建構函式,設定這些預設值,因此可以修改
static Configuration()
{
    mNumberFormat = CultureInfo.InvariantCulture.NumberFormat;
    mValidCommentChars = new[] { '#', ';', '\'' };
    mIgnoreInlineComments = false;
    mIgnorePreComments = false;
}

  所以如果配置檔案中值可能會出現#號的情況,那你就找一個不出現的 字元,來單獨作為你的註釋標記符,給這個靜態屬性賦值即可。

2.4 字串需要換行的問題

  這個問題也很有意思。如果是一行固定文字,你放在配置檔案,會自動顯示換行,但是讀取的時候,人家是看做一行的。因為沒有換行符結尾。而如果有幾段字元,換行符分割開了,這個時候SharpConfig是肯定不支援的,我們可以看一下SharpConfig中核心的解析函式:

 1 //根據字串解析配置檔案,核心的解析函式
 2 private static Configuration Parse(string source)
 3 {
 4     //重置臨時欄位
 5     mLineNumber = 0;
 6 
 7     Configuration config = new Configuration();
 8     Section currentSection = null;
 9     var preComments = new List<Comment>();
10     
11     using (var reader = new StringReader(source))
12     {
13         string line = null;
14 
15         // 讀取一行,直到結尾(Read until EOF.)
16         while ((line = reader.ReadLine()) != null)
17         {
18             mLineNumber++;
19             //刪除前後空白字元
20             line = line.Trim();
21 
22             //這裡擴充套件核心的換行支援,使用 3個 ... 開頭,說明是上一個設定的換行
23             //每一次行都讀取下一行試一下,如果有...,就新增
24             if(line.StartsWith("..."))
25             {
26                 var text = "\r\n" + line.Substring(3);
27                 currentSection[currentSection.SettingCount - 1].Value += text;
28                 continue;
29             }
30             //如果是空行跳過
31             if (string.IsNullOrEmpty(line)) continue;
32 
33             int commentIndex = 0;
34             var comment = ParseComment(line, out commentIndex);
35 
36             if (!mIgnorePreComments && commentIndex == 0)
37             {
38                 // 解析註釋行,新增到 註釋列表中去
39                 preComments.Add(comment);
40                 continue;
41             }
42             else if (!mIgnoreInlineComments && commentIndex > 0)
43             {
44                 // 去掉這一行的註釋
45                 line = line.Remove(commentIndex).Trim();
46             }
47 
48             //如果開始字元是 [ ,說明是 節(Sections)
49             if (line.StartsWith("["))
50             {
51                 #region 節解析
52                 currentSection = ParseSection(line);
53 
54                 if (!mIgnoreInlineComments)
55                     currentSection.Comment = comment;
56 
57                 if (config.Contains(currentSection.Name))
58                 {
59                     throw new ParserException(string.Format(
60                         "The section '{0}' was already declared in the configuration.",
61                         currentSection.Name), mLineNumber);
62                 }
63 
64                 if (!mIgnorePreComments && preComments.Count > 0)
65                 {
66                     currentSection.mPreComments = new List<Comment>(preComments);
67                     preComments.Clear();
68                 }
69 
70                 config.mSections.Add(currentSection);
71                 #endregion
72             }
73             else  //否則就是鍵值設定行
74             {
75                 //解析設定行
76                 Setting setting = ParseSetting(line);
77 
78                 if (!mIgnoreInlineComments) setting.Comment = comment;
79 
80                 if (currentSection == null) throw new ParserException(string.Format("The setting '{0}' has to be in a section.", setting.Name), mLineNumber);
81 
82                 if (currentSection.Contains(setting.Name)) throw new ParserException(string.Format("The setting '{0}' was already declared in the section.", setting.Name), mLineNumber);
83 
84                 if (!mIgnorePreComments && preComments.Count > 0)
85                 {
86                     setting.mPreComments = new List<Comment>(preComments);
87                     preComments.Clear();
88                 }
89                 currentSection.Add(setting);
90             }
91 
92         }
93     }
94     return config;
95 }
View Code

  上面我進行了註釋的翻譯,從流程可以看到,SharpConfig是依次讀取每一行直接進行轉換,看看滿足什麼特徵,然後進行處理。如果直接換行,沒有Name和=號對應,那會報錯。所以我們自己動手,擴充套件一下,其實非常簡單。

  上述程式碼是我已經擴充套件好的,思路很簡單,我們選得一個標記字串,這裡使用“...”作為值換行的標記,每一次讀取新行的值後,我們先進行換行判斷,如果包含"...",就預設作為當前節最後一個Setting的附加值,手動加上換行符"\r\n"。所以核心的程式碼其實很簡單,主要是你要搞清楚流程,要加在哪裡:

//這裡擴充套件核心的換行支援,使用 3個 ... 開頭,說明是上一個設定的換行
//每一次行都讀取下一行試一下,如果有...,就新增
if(line.StartsWith("..."))
{
    var text = "\r\n" + line.Substring(3);
    currentSection[currentSection.SettingCount - 1].Value += text;
    continue;
}

  我們看一個例子,來測試一下換行值的情況,下面是配置檔案:

控制檯直接讀取這個值的程式碼:

//按檔名稱載入配置檔案
Configuration config = Configuration.LoadFromFile("example.ini",
                        Encoding.GetEncoding("gb2312"));
Section section = config["General"];
string someString = section["SomeString"].Value;
Console.WriteLine("字串SomeString值:{0}", someString);

結果如下,已經預設進行換行了:

3.資源

  現在寫部落格頻繁了,也有大量程式碼,所以開始使用github,這次就作為我的第一個開源專案程式碼吧,把我修改後的原始碼發在上面,大家去下載好了。

另外,我也對SharpConfig進行了翻譯,可以便於大家更方便的使用,原始碼可以去github的地址下載,幫助文件也在裡面哦。這裡先截個圖:

相關推薦

.NET平臺開源專案(5)深入使用擴充套件SharpConfig元件

  上個月在文章:這些.NET開源專案你知道嗎?讓.NET開源來得更加猛烈些吧  和 .NET平臺開源專案速覽(1)SharpConfig配置檔案讀寫元件 中都提到了SharpConfig元件,簡單輕量級,速度快,而且還有比較深入的使用介紹。在文章釋出後,也有網友提到一些問題,當時我也沒仔細去分析,在這次我親

.NET平臺開源專案-最快的物件對映元件Tiny Mapper之專案實踐

心情小札:近期換了工作,苦逼於22:00後下班,房間一篇狼藉~ 小翠鄙視到:"你就適合生活在垃圾堆中!!!" 看評論也是挺有價值,同時也看到許多新手同學問道在實際專案中使用的情況。 下面就原作者的程式碼的基礎上略作調整,闡述一下在實際專案場景中的使用: 第一步:瞭解類庫方法:TinyMapper 主

.NET平臺開源專案(9)軟體序列號生成元件SoftwareProtector介紹使用

  在文章:這些.NET開源專案你知道嗎?讓.NET開源來得更加猛烈些吧!(第二輯)中,給大家初步介紹了一下Software Protector序列號生成元件。今天就通過一篇簡單的文章來預覽一下其強大的功能。雖然我人為其已經基本滿足了一個軟體序列號的所有要素,但至於大家用不用得上,還得看大家的需求。總的來

.NET平臺開源專案(8)Expression Evaluator表示式計算元件使用

  在文章:這些.NET開源專案你知道嗎?讓.NET開源來得更加猛烈些吧!(第二輯)中,給大家初步介紹了一下Expression Evaluator驗證元件。那裡只是概述了一下,並沒有對其使用和強大功能做深入研究,所以今天就通過一篇簡單的文章來預覽一下其強大的功能。本文曾在【原創】.NET開源表示式計算元

.NET平臺開源專案(10)FluentValidation驗證元件深入使用(二)

    在上一篇文章:.NET平臺開源專案速覽(6)FluentValidation驗證元件介紹與入門(一) 中,給大家初步介紹了一下FluentValidation驗證元件的使用情況。文章從構建間的驗證器開始,到最後的結果,以及複雜驗證等都做了比較深入的講解和使用。但其實一個完整的元件是麻雀雖小五臟俱全

.NET平臺開源專案(14)最快的物件對映元件Tiny Mapper

    好久沒有寫文章,工作甚忙,但每日還是關注.NET領域的開源專案。五一休息,放鬆了一下之後,今天就給大家介紹一個輕量級的物件對映工具Tiny Mapper:號稱是.NET平臺最快的物件對映元件。那就一起看看呢。 臨時更新:感謝@ 的意見,為了避免新手誤解,這裡說明一下,Tiny Mappe

.NET平臺開源專案(20)Newlife.Core中簡單靈活的配置檔案

如果用知乎,可以關注專欄: 記得5年前開始拼命翻讀X元件的原始碼,特別是XCode,但對Newlife.Core 的東西瞭解很少,最多隻是會用用,而且用到的只是九牛一毛。裡面好用的東西太多了。 最近一年時間,零零散散又學了很多,也瞭解了很多,不會寫那總要學會用吧,今天就給大家介紹裡面非常好用的自定義配置檔

.NET平臺開源專案(19)Power BI神器DAX Studio

  PowerBI更新頻繁,已經有點更不上的節奏,一直在關注和學習中,基本的一些操作大概是沒問題,更重要的是注重Power Query,M函式,以及DAX的使用,這才是核心。     上個月研究了DAX的一些語法和公式,發現這玩意看起來簡單,但其實功能非常強大,所以就想和寫程式碼一樣,弄個工具試一下。

.NET平臺開源專案(21)Cron任務排程CronNET

Quartznet大名鼎鼎應該很少有人不知道,相關的開源專案很多,不過那東東對新手來說,有點晦澀,加上哪個Cron表示式,可能一進去雲裡霧裡的。今天給大家介紹一個簡單的在.NET平臺上執行Cron計劃任務的元件CronNET。同時也給大家推介幾個Cron表示式的工具。 1.Cron介紹和工具

.NET平臺開源專案(7)關於NoSQL資料庫LiteDB的分頁查詢解決過程

  在文章:這些.NET開源專案你知道嗎?讓.NET開源來得更加猛烈些吧!(第二輯) 與 .NET平臺開源專案速覽(3)小巧輕量級NoSQL檔案資料庫LiteDB中,介紹了LiteDB的基本使用情況以及部分技術細節,我還沒有在實際系統中大量使用,但文章釋出後,有不少網友( )反應在實際專案中使用過,效果還

.NET平臺開源專案(11)KwCombinatorics排列組合使用案例(1)

    今年上半年,我在KwCombinatorics系列文章中,重點介紹了KwCombinatorics元件的使用情況,其實這個元件我5年前就開始用了,非常方便,麻雀雖小五臟俱全。所以一直非常喜歡,才寫了幾篇文章推薦給大家。最近在計算足球彩票結果組合過程中,使用的到了其功能,生成排列,非常具有代表性,而且也

.NET平臺開源專案(1)SharpConfig配置檔案讀寫元件

在.NET平臺日常開發中,讀取配置檔案是一個很常見的需求。以前都是使用System.Configuration.ConfigurationSettings來操作,這個說實話,搞起來比較費勁。不知道大家有沒有同感。所以更多時候我還是喜歡使用開源的東西,更加方便簡潔,也穩定。省去自己的麻煩。今天就介紹一個非常精緻

.NET平臺開源專案(3)小巧輕量級NoSQL檔案資料庫LiteDB

    今天給大家介紹一個不錯的小巧輕量級的NoSQL檔案資料庫LiteDB。本部落格在2013年也介紹過2款.NET平臺的開源資料庫:     上面2個數據庫我的實際的專案中用過,還不錯。當然資料量很小,主要是客戶比較變態,必須要用xml檔案儲存,就想到了,另外NDatabase只是自己覺得好玩,

.NET平臺開源專案(2)Compare .NET Objects物件比較元件

    .NET平臺開源專案速覽今天介紹一款小巧強大的物件比較元件。可以更詳細的獲取2個物件的差別,並記錄具體差別,比較過程和要求可以靈活配置。 1.Compare .NET Objects介紹     Compare .NET Objects元件是.NET平臺用於深入比較2個.NET物件的開源元

.NET平臺開源專案(13)機器學習元件Accord.NET框架功能介紹

    Accord.NET Framework是在AForge.NET專案的基礎上封裝和進一步開發而來。因為AForge.NET更注重與一些底層和廣度,而Accord.NET Framework更注重與機器學習演算法以及提供計算機視訊、音訊、訊號處理以及統計應用相關的解決方案。該專案使用C#語言編寫,專

.NET平臺開源專案(4).NET文件生成工具ADB及使用

    很久以前就使用ADB這個工具來生成專案的幫助文件。功能強大,在學習一些開源專案的過程中,官方沒有提供CHM幫助文件,所以為了快速的瞭解專案結構和註釋。就生成文件來自己看,非常好用。這也是一個學習方法吧。例如本文在:   上述2篇文章中最後的資源中就手動製作了CHM幫助文件。有時候我們還可

.NET平臺開源專案(6)FluentValidation驗證元件介紹入門(一)

    在文章:這些.NET開源專案你知道嗎?讓.NET開源來得更加猛烈些吧!(第二輯)中,給大家初步介紹了一下FluentValidation驗證元件。那裡只是概述了一下,並沒有對其使用和強大功能做深入研究,所以今天以及接下去的幾篇文章就專門介紹這個元件。不僅僅是它小,輕量級,優雅,而且一直在持續更新中

.NET平臺開源專案(12)雜湊演算法集合類庫HashLib

    .NET的System.Security.Cryptography名稱空間本身是提供加密服務,雜湊函式,對稱與非對稱加密演算法等功能。實際上,大部分情況下已經滿足了需求,而且.NET實現的都是目前國際上比較權威的,標準化的演算法,所以還是安全可靠的。但也有一些場合,需要自己實現一些安全雜湊演算法。

.NET平臺開源專案(18)C#平臺JSON實體類生成器JSON C# Class Generator

    去年,我在一篇文章用原始方法解析複雜字串,json一定要用JsonMapper麼?中介紹了簡單的JSON解析的問題,那種方法在當時的環境是非常方便的,因為不需要生成實體類,結構很容易解析。但隨著業務的變化,也會碰到超級變態的JSON,如果還按照以前的思路,會把人搞抽風掉,一旦結構變化,又要重來。所

.NET平臺開源專案(16)C#寫PDF檔案類庫PDF File Writer介紹

    1年前,我在文章:這些.NET開源專案你知道嗎?.NET平臺開源文件與報表處理元件集合(三)中(第9個專案),給大家推薦了一個開源免費的PDF讀寫元件 PDFSharp,PDFSharp我2年前就看過,用過簡單的例子,不過程式碼沒有寫成專門的文章。最近在查詢資料的時候,又發現一款小巧的寫PDF檔案