Util應用程序框架公共操做類(二):數據類型轉換公共操做類(源碼篇)

  上一篇介紹了數據類型轉換的一些狀況,能夠看出,若是不進行封裝,有可能致使比較混亂的代碼。本文經過TDD方式把數據類型轉換公共操做類開發出來,並提供源碼下載。git

  咱們在 應用程序框架實戰十一:建立VS解決方案與程序集 一文已經建立了解決方案,包含一個類庫項目和一個單元測試項目。單元測試將使用.Net自帶的 MsTest,另外經過Resharper工具來觀察測試結果。程序員

  首先考慮咱們指望的API長成什麼樣子。基於TDD開發,其中一個做用是幫助程序員設計指望的API,這稱爲意圖導向編程。編程

  由於數據類型轉換是Convert,因此咱們先在單元測試項目中建立一個ConvertTest的類文件。 框架

  類建立好之後,我先隨便建立一個方法Test,以迅速展開工做。測試的方法名Test,我是隨便起的,由於如今還不清楚API是什麼樣,我一會再回過頭來改。ide

using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Util.Tests { /// <summary>
    /// 類型轉換公共操做類測試 /// </summary>
 [TestClass] public class ConvertTest { [TestMethod] public void Test() { } } } 

  爲了照顧尚未使用單元測試的朋友,我在這裏簡單介紹一下MsTest。MsTest是.Net仿照JUnit打造的一個單元測試框架。在單元測試類上須要添加一個TestClass特性,在測試方法上添加TestMethod特性,用來識別哪些類的操做須要測試。還有一些其它特性,在用到的時候我再介紹。工具

  如今先來實現一個最簡單的功能,把字符串」1」轉換爲整數1。性能

[TestMethod] public void Test() { Assert.AreEqual( 1, Util.ConvertHelper.ToInt( "1" ) ); }

  我把經常使用公共操做類儘可能放到頂級命名空間Util,這樣我就能夠經過編寫Util.來彈出代碼提示,這樣我連經常使用類也不用記了。單元測試

  使用ConvertHelper是一個常規命名,大多數開發人員能夠理解它是一個類型轉換的公共操做類。我也這樣用了多年,不事後面我發現Util.ConvertHelper有點囉嗦,因此我簡化成Util.Convert,但Convert又和系統重名了,因此我如今使用Util.Conv,你不必定要按個人這個命名,你可使用ConvertHelper這樣的命名以提升代碼清晰度。測試

  System.Convert使用ToInt32來精確表示int是一個32位的數字,不過咱們的公共操做類不用這樣精確,ToInt就能夠了,若是要封裝ToInt64呢,我就用ToLong,這樣比較符合個人習慣。ui

  如今代碼被簡化成了下面的代碼。

Assert.AreEqual( 1, Util.Conv.ToInt( "1" ) );

  Assert在測試中用來斷言,斷言就是比較實際計算出來的值是否和預期一致,Assert包含大量比較方法,AreEqual使用頻率最高,用來比較預期值(左邊)與實際值(右邊)是否值相等,還有一個AreSame方法用來比較是否引用相等。   

    

  因爲Conv類還未建立,因此顯示一個紅色警告。   如今在Util類庫項目中建立一個Conv類。

  建立了Conv類之後,單元測試代碼檢測到Conv,但ToInt方法未建立,因此紅色警告轉移到ToInt方法。

  如今用鼠標左鍵單擊紅色ToInit方法,Resharper在左側顯示一個紅色的燈泡。

  單擊紅色燈泡提示,選擇第一項」Create Method ‘Conv.ToInt’」。

  Resharper會在Conv類中自動建立一個ToInt方法。

public class Conv { public static int ToInt( string s ) { throw new NotImplementedException(); } } 

  方法體拋出一個未實現的異常,這正是咱們想要的。TDD的口訣是「紅、綠、重構」,第一步須要先保證方法執行失敗,顯示紅色警告。至於未何須要測試先行,以及首先執行失敗,牽扯TDD開發價值觀,請你們參考相關資料。

  準備工做已經就緒,如今能夠運行測試了。安裝了Resharper之後,在添加了TestClass特性的左側,會看見兩個重疊在一塊兒的圓形圖標。另外,在TestMethod特性左側,有一個黑白相間的圓形圖標。

   單擊Test方法左側的圖標,而後點擊Run按鈕。若是單擊TestClass特性左側的圖標,會運行該類全部測試。

  測試開始運行,並顯示紅色警告,提示未實現的異常,第一步完成。

  爲了實現功能,如今來添加ToInt方法的代碼。

public static int ToInt( string s ) { int result; int.TryParse( s, out result ); return result; }

  再次運行測試,已經可以成功經過,第二步完成。 

  第三步是進行重構,如今看哪些地方能夠重構。參數s看起來有點不爽,改爲data,並添加XML註釋。

        /// <summary>
        /// 轉換爲整型 /// </summary>
        /// <param name="data">數據</param>
        public static int ToInt( string data ) { int result; int.TryParse( data, out result ); return result; } 

  另外重構一下測試,爲了更容易找到相關測試,通常測試文件名使用類名+Test,如今測試文件名改爲ConvTest.cs,測試類名改爲ConvTest。把測試方法名改爲TestToInt,並添加XML註釋。

        /// <summary>
        /// 測試轉換爲整型 /// </summary>
 [TestMethod] public void TestToInt() { Assert.AreEqual( 1, Util.Conv.ToInt( "1" ) ); } 

  關於測試的命名,不少著做都提出了本身不一樣的方法。在《.Net單元測試藝術》中,做者建議使用三部分進行組合命名。還有一些著做建議將測試內容用下劃線分隔單詞,拼成一個長句子,以方便閱讀和理解。這可能對英文水平好的人頗有效,不過個人英文水平很爛,我拿一些單詞拼成一個長句之後,發現更難理解了。因此我所採用的測試方法命名可能不必定好,你能夠按你容易理解的方式來命名。

  重構以後,須要從新測試代碼,以觀察是否致使失敗。

  上面簡單介紹了TDD的一套開發流程,主要爲了照顧尚未體驗過單元測試的人,後面直接粘貼代碼,以免這樣低效的敘述方式。

  單元測試代碼以下。

 1 using System;  2 using Microsoft.VisualStudio.TestTools.UnitTesting;  3 
 4 namespace Util.Tests {  5     /// <summary>
 6     /// 類型轉換公共操做類測試  7     /// </summary>
 8  [TestClass]  9     public class ConvTest {  10 
 11         #region ToInt(轉換爲整型)
 12 
 13         /// <summary>
 14         ///轉換爲整型,值爲null  15         ///</summary>
 16  [TestMethod]  17         public void TestToInt_Null() {  18             Assert.AreEqual( 0, Util.Conv.ToInt( null ) );  19  }  20 
 21         /// <summary>
 22         ///轉換爲整型,值爲空字符串  23         ///</summary>
 24  [TestMethod]  25         public void TestToInt_Empty() {  26             Assert.AreEqual( 0, Util.Conv.ToInt( "" ) );  27  }  28 
 29         /// <summary>
 30         ///轉換爲整型,無效值  31         ///</summary>
 32  [TestMethod]  33         public void TestToInt_Invalid() {  34             Assert.AreEqual( 0, Util.Conv.ToInt( "1A" ) );  35  }  36 
 37         /// <summary>
 38         ///轉換爲整型,有效值  39         ///</summary>
 40  [TestMethod]  41         public void TestToInt() {  42             Assert.AreEqual( 1, Util.Conv.ToInt( "1" ) );  43             Assert.AreEqual( 1778020, Util.Conv.ToInt( "1778019.7801684" ) );  44  }  45 
 46         #endregion
 47 
 48         #region ToIntOrNull(轉換爲可空整型)
 49 
 50         /// <summary>
 51         ///轉換爲可空整型,值爲null  52         ///</summary>
 53  [TestMethod]  54         public void TestToIntOrNull_Null() {  55             Assert.IsNull( Util.Conv.ToIntOrNull( null ) );  56  }  57 
 58         /// <summary>
 59         ///轉換爲可空整型,值爲空字符串  60         ///</summary>
 61  [TestMethod]  62         public void TestToIntOrNull_Empty() {  63             Assert.IsNull( Util.Conv.ToIntOrNull( "" ) );  64  }  65 
 66         /// <summary>
 67         ///轉換爲可空整型,無效值  68         ///</summary>
 69  [TestMethod]  70         public void TestToIntOrNull_Invalid() {  71             Assert.IsNull( Util.Conv.ToIntOrNull( "1A" ) );  72  }  73 
 74         /// <summary>
 75         ///轉換爲可空整型,值爲0  76         ///</summary>
 77  [TestMethod]  78         public void TestToIntOrNull_0() {  79             Assert.AreEqual( 0, Util.Conv.ToIntOrNull( "0" ) );  80  }  81 
 82         /// <summary>
 83         ///轉換爲可空整型,有效值  84         ///</summary>
 85  [TestMethod]  86         public void TestToIntOrNull() {  87             Assert.AreEqual( 1, Util.Conv.ToIntOrNull( "1" ) );  88  }  89 
 90         #endregion
 91 
 92         #region ToDouble(轉換爲雙精度浮點數)
 93 
 94         /// <summary>
 95         ///轉換爲雙精度浮點數,值爲null  96         ///</summary>
 97  [TestMethod]  98         public void TestToDouble_Null() {  99             Assert.AreEqual( 0, Util.Conv.ToDouble( null ) ); 100  } 101 
102         /// <summary>
103         ///轉換爲雙精度浮點數,值爲空字符串 104         ///</summary>
105  [TestMethod] 106         public void TestToDouble_Empty() { 107             Assert.AreEqual( 0, Util.Conv.ToDouble( "" ) ); 108  } 109 
110         /// <summary>
111         ///轉換爲雙精度浮點數,無效值 112         ///</summary>
113  [TestMethod] 114         public void TestToDouble_Invalid() { 115             Assert.AreEqual( 0, Util.Conv.ToDouble( "1A" ) ); 116  } 117 
118         /// <summary>
119         ///轉換爲雙精度浮點數,有效值 120         ///</summary>
121  [TestMethod] 122         public void TestToDouble() { 123             Assert.AreEqual( 1.2, Util.Conv.ToDouble( "1.2" ) ); 124  } 125 
126         /// <summary>
127         /// 轉換爲雙精度浮點數,指定2位小數位數 128         ///</summary>
129  [TestMethod()] 130         public void TestToDouble_DigitsIs2() { 131             Assert.AreEqual( 12.36, Util.Conv.ToDouble( "12.355", 2 ) ); 132  } 133 
134         #endregion
135 
136         #region ToDoubleOrNull(轉換爲可空雙精度浮點數)
137 
138         /// <summary>
139         ///轉換爲可空雙精度浮點數,值爲null 140         ///</summary>
141  [TestMethod] 142         public void TestToDoubleOrNull_Null() { 143             Assert.IsNull( Util.Conv.ToDoubleOrNull( null ) ); 144  } 145 
146         /// <summary>
147         ///轉換爲可空雙精度浮點數,值爲空字符串 148         ///</summary>
149  [TestMethod] 150         public void TestToDoubleOrNull_Empty() { 151             Assert.IsNull( Util.Conv.ToDoubleOrNull( "" ) ); 152  } 153 
154         /// <summary>
155         ///轉換爲可空雙精度浮點數,無效值 156         ///</summary>
157  [TestMethod] 158         public void TestToDoubleOrNull_Invalid() { 159             Assert.IsNull( Util.Conv.ToDoubleOrNull( "1A" ) ); 160  } 161 
162         /// <summary>
163         ///轉換爲可空雙精度浮點數,值爲0 164         ///</summary>
165  [TestMethod] 166         public void TestToDoubleOrNull_0() { 167             Assert.AreEqual( 0, Util.Conv.ToDoubleOrNull( "0" ) ); 168  } 169 
170         /// <summary>
171         ///轉換爲可空雙精度浮點數,有效值 172         ///</summary>
173  [TestMethod] 174         public void TestToDoubleOrNull() { 175             Assert.AreEqual( 1.2, Util.Conv.ToDoubleOrNull( "1.2" ) ); 176  } 177 
178         #endregion
179 
180         #region ToDecimal(轉換爲高精度浮點數)
181 
182         /// <summary>
183         ///轉換爲高精度浮點數,值爲null 184         ///</summary>
185  [TestMethod] 186         public void TestToDecimal_Null() { 187             Assert.AreEqual( 0, Util.Conv.ToDecimal( null ) ); 188  } 189 
190         /// <summary>
191         ///轉換爲高精度浮點數,值爲空字符串 192         ///</summary>
193  [TestMethod] 194         public void TestToDecimal_Empty() { 195             Assert.AreEqual( 0, Util.Conv.ToDecimal( "" ) ); 196  } 197 
198         /// <summary>
199         ///轉換爲高精度浮點數,無效值 200         ///</summary>
201  [TestMethod] 202         public void TestToDecimal_Invalid() { 203             Assert.AreEqual( 0, Util.Conv.ToDecimal( "1A" ) ); 204  } 205 
206         /// <summary>
207         ///轉換爲高精度浮點數,有效值 208         ///</summary>
209  [TestMethod] 210         public void TestToDecimal() { 211             Assert.AreEqual( 1.2M, Util.Conv.ToDecimal( "1.2" ) ); 212  } 213 
214         /// <summary>
215         /// 轉換爲高精度浮點數,指定2位小數位數 216         ///</summary>
217  [TestMethod()] 218         public void TestToDecimal_DigitsIs2() { 219             Assert.AreEqual( 12.24M, Util.Conv.ToDecimal( "12.235", 2 ) ); 220  } 221 
222         #endregion
223 
224         #region ToDecimalOrNull(轉換爲可空高精度浮點數)
225 
226         /// <summary>
227         ///轉換爲可空高精度浮點數,值爲null 228         ///</summary>
229  [TestMethod] 230         public void TestToDecimalOrNull_Null() { 231             Assert.IsNull( Util.Conv.ToDecimalOrNull( null ) ); 232  } 233 
234         /// <summary>
235         ///轉換爲可空高精度浮點數,值爲空字符串 236         ///</summary>
237  [TestMethod] 238         public void TestToDecimalOrNull_Empty() { 239             Assert.IsNull( Util.Conv.ToDecimalOrNull( "" ) ); 240  } 241 
242         /// <summary>
243         ///轉換爲可空高精度浮點數,無效值 244         ///</summary>
245  [TestMethod] 246         public void TestToDecimalOrNull_Invalid() { 247             Assert.IsNull( Util.Conv.ToDecimalOrNull( "1A" ) ); 248  } 249 
250         /// <summary>
251         ///轉換爲可空高精度浮點數,無效值,指定2位小數位數 252         ///</summary>
253  [TestMethod] 254         public void TestToDecimalOrNull_Invalid_DigitsIs2() { 255             Assert.IsNull( Util.Conv.ToDecimalOrNull( "1A", 2 ) ); 256  } 257 
258         /// <summary>
259         ///轉換爲可空高精度浮點數,值爲0 260         ///</summary>
261  [TestMethod] 262         public void TestToDecimalOrNull_0() { 263             Assert.AreEqual( 0, Util.Conv.ToDecimalOrNull( "0" ) ); 264  } 265 
266         /// <summary>
267         ///轉換爲可空高精度浮點數,有效值 268         ///</summary>
269  [TestMethod] 270         public void TestToDecimalOrNull() { 271             Assert.AreEqual( 1.2M, Util.Conv.ToDecimalOrNull( "1.2" ) ); 272  } 273 
274         /// <summary>
275         /// 轉換爲可空高精度浮點數,指定2位小數位數 276         ///</summary>
277  [TestMethod()] 278         public void ToDecimalOrNull_DigitsIs2() { 279             Assert.AreEqual( 12.24M, Util.Conv.ToDecimalOrNull( "12.235", 2 ) ); 280  } 281 
282         #endregion
283 
284         #region ToGuid(轉換爲Guid)
285 
286         /// <summary>
287         ///轉換爲Guid,值爲null 288         ///</summary>
289  [TestMethod] 290         public void TestToGuid_Null() { 291             Assert.AreEqual( Guid.Empty, Util.Conv.ToGuid( null ) ); 292  } 293 
294         /// <summary>
295         ///轉換爲Guid,值爲空字符串 296         ///</summary>
297  [TestMethod] 298         public void TestToGuid_Empty() { 299             Assert.AreEqual( Guid.Empty, Util.Conv.ToGuid( "" ) ); 300  } 301 
302         /// <summary>
303         ///轉換爲Guid,無效值 304         ///</summary>
305  [TestMethod] 306         public void TestToGuid_Invalid() { 307             Assert.AreEqual( Guid.Empty, Util.Conv.ToGuid( "1A" ) ); 308  } 309 
310         /// <summary>
311         ///轉換爲Guid,有效值 312         ///</summary>
313  [TestMethod] 314         public void TestToGuid() { 315             Assert.AreEqual( new Guid( "B9EB56E9-B720-40B4-9425-00483D311DDC" ), Util.Conv.ToGuid( "B9EB56E9-B720-40B4-9425-00483D311DDC" ) ); 316  } 317 
318         #endregion
319 
320         #region ToGuidOrNull(轉換爲可空Guid)
321 
322         /// <summary>
323         ///轉換爲可空Guid,值爲null 324         ///</summary>
325  [TestMethod] 326         public void TestToGuidOrNull_Null() { 327             Assert.IsNull( Util.Conv.ToGuidOrNull( null ) ); 328  } 329 
330         /// <summary>
331         ///轉換爲可空Guid,值爲空字符串 332         ///</summary>
333  [TestMethod] 334         public void TestToGuidOrNull_Empty() { 335             Assert.IsNull( Util.Conv.ToGuidOrNull( "" ) ); 336  } 337 
338         /// <summary>
339         ///轉換爲可空Guid,無效值 340         ///</summary>
341  [TestMethod] 342         public void TestToGuidOrNull_Invalid() { 343             Assert.IsNull( Util.Conv.ToGuidOrNull( "1A" ) ); 344  } 345 
346         /// <summary>
347         ///轉換爲可空Guid,有效值 348         ///</summary>
349  [TestMethod] 350         public void TestToGuidOrNull() { 351             Assert.AreEqual( new Guid( "B9EB56E9-B720-40B4-9425-00483D311DDC" ), Util.Conv.ToGuidOrNull( "B9EB56E9-B720-40B4-9425-00483D311DDC" ) ); 352  } 353 
354         #endregion
355 
356         #region ToGuidList(轉換爲Guid集合)
357 
358         /// <summary>
359         /// 轉換爲Guid集合,驗證空字符串 360         /// </summary>
361  [TestMethod] 362         public void TestToGuidList_Empty() { 363             Assert.AreEqual( 0, Util.Conv.ToGuidList( "" ).Count ); 364  } 365 
366         /// <summary>
367         /// 轉換爲Guid集合,驗證最後爲逗號 368         /// </summary>
369  [TestMethod] 370         public void TestToGuidList_LastIsComma() { 371             Assert.AreEqual( 1, Util.Conv.ToGuidList( "83B0233C-A24F-49FD-8083-1337209EBC9A," ).Count ); 372  } 373 
374         /// <summary>
375         /// 轉換爲Guid集合,驗證中間包含逗號 376         /// </summary>
377  [TestMethod] 378         public void TestToGuidList_MiddleIsComma() { 379             const string guid = "83B0233C-A24F-49FD-8083-1337209EBC9A,,EAB523C6-2FE7-47BE-89D5-C6D440C3033A,"; 380             Assert.AreEqual( 2, Util.Conv.ToGuidList( guid ).Count ); 381             Assert.AreEqual( new Guid( "83B0233C-A24F-49FD-8083-1337209EBC9A" ), Util.Conv.ToGuidList( guid )[0] ); 382             Assert.AreEqual( new Guid( "EAB523C6-2FE7-47BE-89D5-C6D440C3033A" ), Util.Conv.ToGuidList( guid )[1] ); 383  } 384 
385         /// <summary>
386         /// 轉換爲Guid集合,僅1個Guid 387         /// </summary>
388  [TestMethod] 389         public void TestToGuidList_1Guid() { 390             const string guid = "83B0233C-A24F-49FD-8083-1337209EBC9A"; 391             Assert.AreEqual( 1, Util.Conv.ToGuidList( guid ).Count ); 392             Assert.AreEqual( new Guid( guid ), Util.Conv.ToGuidList( guid )[0] ); 393  } 394 
395         /// <summary>
396         /// 轉換爲Guid集合,2個Guid 397         /// </summary>
398  [TestMethod] 399         public void TestToGuidList_2Guid() { 400             const string guid = "83B0233C-A24F-49FD-8083-1337209EBC9A,EAB523C6-2FE7-47BE-89D5-C6D440C3033A"; 401             Assert.AreEqual( 2, Util.Conv.ToGuidList( guid ).Count ); 402             Assert.AreEqual( new Guid( "83B0233C-A24F-49FD-8083-1337209EBC9A" ), Util.Conv.ToGuidList( guid )[0] ); 403             Assert.AreEqual( new Guid( "EAB523C6-2FE7-47BE-89D5-C6D440C3033A" ), Util.Conv.ToGuidList( guid )[1] ); 404  } 405 
406         #endregion
407 
408         #region ToDate(轉換爲日期)
409 
410         /// <summary>
411         ///轉換爲日期,值爲null 412         ///</summary>
413  [TestMethod] 414         public void TestToDate_Null() { 415             Assert.AreEqual( DateTime.MinValue, Util.Conv.ToDate( null ) ); 416  } 417 
418         /// <summary>
419         ///轉換爲日期,值爲空字符串 420         ///</summary>
421  [TestMethod] 422         public void TestToDate_Empty() { 423             Assert.AreEqual( DateTime.MinValue, Util.Conv.ToDate( "" ) ); 424  } 425 
426         /// <summary>
427         ///轉換爲日期,無效值 428         ///</summary>
429  [TestMethod] 430         public void TestToDate_Invalid() { 431             Assert.AreEqual( DateTime.MinValue, Util.Conv.ToDate( "1A" ) ); 432  } 433 
434         /// <summary>
435         ///轉換爲日期,有效值 436         ///</summary>
437  [TestMethod] 438         public void TestToDate() { 439             Assert.AreEqual( new DateTime( 2000, 1, 1 ), Util.Conv.ToDate( "2000-1-1" ) ); 440  } 441 
442         #endregion
443 
444         #region ToDateOrNull(轉換爲可空日期)
445 
446         /// <summary>
447         ///轉換爲可空日期,值爲null 448         ///</summary>
449  [TestMethod] 450         public void TestToDateOrNull_Null() { 451             Assert.IsNull( Util.Conv.ToDateOrNull( null ) ); 452  } 453 
454         /// <summary>
455         ///轉換爲可空日期,值爲空字符串 456         ///</summary>
457  [TestMethod] 458         public void TestToDateOrNull_Empty() { 459             Assert.IsNull( Util.Conv.ToDateOrNull( "" ) ); 460  } 461 
462         /// <summary>
463         ///轉換爲可空日期,無效值 464         ///</summary>
465  [TestMethod] 466         public void TestToDateOrNull_Invalid() { 467             Assert.IsNull( Util.Conv.ToDateOrNull( "1A" ) ); 468  } 469 
470         /// <summary>
471         ///轉換爲可空日期,有效值 472         ///</summary>
473  [TestMethod] 474         public void TestToDateOrNull() { 475             Assert.AreEqual( new DateTime( 2000, 1, 1 ), Util.Conv.ToDateOrNull( "2000-1-1" ) ); 476  } 477 
478         #endregion
479 
480         #region ToBool(轉換爲布爾值)
481 
482         /// <summary>
483         ///轉換爲布爾值,值爲null 484         ///</summary>
485  [TestMethod] 486         public void TestToBool_Null() { 487             Assert.AreEqual( false, Util.Conv.ToBool( null ) ); 488  } 489 
490         /// <summary>
491         ///轉換爲布爾值,值爲空字符串 492         ///</summary>
493  [TestMethod] 494         public void TestToBool_Empty() { 495             Assert.AreEqual( false, Util.Conv.ToBool( "" ) ); 496  } 497 
498         /// <summary>
499         ///轉換爲布爾值,無效值 500         ///</summary>
501  [TestMethod] 502         public void TestToBool_Invalid() { 503             Assert.AreEqual( false, Util.Conv.ToBool( "1A" ) ); 504  } 505 
506         /// <summary>
507         ///轉換爲布爾值,值爲False 508         ///</summary>
509  [TestMethod] 510         public void TestToBool_False() { 511             Assert.AreEqual( false, Util.Conv.ToBool( "0" ) ); 512             Assert.AreEqual( false, Util.Conv.ToBool( "" ) ); 513             Assert.AreEqual( false, Util.Conv.ToBool( "no" ) ); 514             Assert.AreEqual( false, Util.Conv.ToBool( "No" ) ); 515             Assert.AreEqual( false, Util.Conv.ToBool( "false" ) ); 516             Assert.AreEqual( false, Util.Conv.ToBool( "False" ) ); 517  } 518 
519         /// <summary>
520         ///轉換爲布爾值,值爲True 521         ///</summary>
522  [TestMethod] 523         public void TestToBool_True() { 524             Assert.AreEqual( true, Util.Conv.ToBool( "1" ) ); 525             Assert.AreEqual( true, Util.Conv.ToBool( "" ) ); 526             Assert.AreEqual( true, Util.Conv.ToBool( "yes" ) ); 527             Assert.AreEqual( true, Util.Conv.ToBool( "Yes" ) ); 528             Assert.AreEqual( true, Util.Conv.ToBool( "true" ) ); 529             Assert.AreEqual( true, Util.Conv.ToBool( "True" ) ); 530  } 531 
532         #endregion
533 
534         #region ToBoolOrNull(轉換爲可空布爾值)
535 
536         /// <summary>
537         ///轉換爲可空布爾值,值爲null 538         ///</summary>
539  [TestMethod] 540         public void TestToBoolOrNull_Null() { 541             Assert.IsNull( Util.Conv.ToBoolOrNull( null ) ); 542  } 543 
544         /// <summary>
545         ///轉換爲可空布爾值,值爲空字符串 546         ///</summary>
547  [TestMethod] 548         public void TestToBoolOrNull_Empty() { 549             Assert.IsNull( Util.Conv.ToBoolOrNull( "" ) ); 550  } 551 
552         /// <summary>
553         ///轉換爲可空布爾值,無效值 554         ///</summary>
555  [TestMethod] 556         public void TestToBoolOrNull_Invalid() { 557             Assert.IsNull( Util.Conv.ToBoolOrNull( "1A" ) ); 558  } 559 
560         /// <summary>
561         ///轉換爲布爾值,值爲False 562         ///</summary>
563  [TestMethod] 564         public void TestToBoolOrNull_False() { 565             Assert.AreEqual( false, Util.Conv.ToBoolOrNull( "0" ) ); 566             Assert.AreEqual( false, Util.Conv.ToBoolOrNull( "" ) ); 567             Assert.AreEqual( false, Util.Conv.ToBoolOrNull( "no" ) ); 568             Assert.AreEqual( false, Util.Conv.ToBoolOrNull( "No" ) ); 569             Assert.AreEqual( false, Util.Conv.ToBoolOrNull( "false" ) ); 570             Assert.AreEqual( false, Util.Conv.ToBoolOrNull( "False" ) ); 571  } 572 
573         /// <summary>
574         ///轉換爲布爾值,值爲True 575         ///</summary>
576  [TestMethod] 577         public void TestToBoolOrNull_True() { 578             Assert.AreEqual( true, Util.Conv.ToBoolOrNull( "1" ) ); 579             Assert.AreEqual( true, Util.Conv.ToBoolOrNull( "" ) ); 580             Assert.AreEqual( true, Util.Conv.ToBoolOrNull( "yes" ) ); 581             Assert.AreEqual( true, Util.Conv.ToBoolOrNull( "Yes" ) ); 582             Assert.AreEqual( true, Util.Conv.ToBoolOrNull( "true" ) ); 583             Assert.AreEqual( true, Util.Conv.ToBoolOrNull( "True" ) ); 584  } 585 
586         #endregion
587 
588         #region ToString(轉換爲字符串)
589 
590         /// <summary>
591         ///轉換爲字符串,值爲null 592         ///</summary>
593  [TestMethod] 594         public void TestToString_Null() { 595             Assert.AreEqual( string.Empty, Util.Conv.ToString( null ) ); 596  } 597 
598         /// <summary>
599         ///轉換爲字符串,值爲空字符串 600         ///</summary>
601  [TestMethod] 602         public void TestToString_Empty() { 603             Assert.AreEqual( string.Empty, Util.Conv.ToString( " " ) ); 604  } 605 
606         /// <summary>
607         ///轉換爲字符串,有效值 608         ///</summary>
609  [TestMethod] 610         public void TestToString() { 611             Assert.AreEqual( "1", Util.Conv.ToString( 1 ) ); 612  } 613 
614         #endregion
615 
616         #region To(通用泛型轉換)
617 
618         #region 目標爲int
619 
620         /// <summary>
621         ///通用泛型轉換,目標爲整數,值爲null 622         ///</summary>
623  [TestMethod] 624         public void TestTo_Int_Null() { 625             Assert.AreEqual( 0, Conv.To<int>( null ) ); 626  } 627 
628         /// <summary>
629         ///通用泛型轉換,目標爲整數,值爲空字符串 630         ///</summary>
631  [TestMethod] 632         public void TestTo_Int_Empty() { 633             Assert.AreEqual( 0, Conv.To<int>( "" ) ); 634  } 635 
636         /// <summary>
637         ///通用泛型轉換,目標爲整數,無效值 638         ///</summary>
639  [TestMethod] 640         public void TestTo_Int_Invalid() { 641             Assert.AreEqual( 0, Conv.To<int>( "1A" ) ); 642  } 643 
644         /// <summary>
645         ///通用泛型轉換,目標爲整數,有效值 646         ///</summary>
647  [TestMethod] 648         public void TestTo_Int() { 649             Assert.AreEqual( 1, Conv.To<int>( "1" ) ); 650  } 651 
652         /// <summary>
653         ///通用泛型轉換,目標爲可空整數,無效值 654         ///</summary>
655  [TestMethod] 656         public void TestTo_IntOrNull_Invalid() { 657             Assert.IsNull( Conv.To<int?>( "1A" ) ); 658  } 659 
660         /// <summary>
661         ///通用泛型轉換,目標爲可空整數,有效值 662         ///</summary>
663  [TestMethod] 664         public void TestTo_IntOrNull() { 665             Assert.AreEqual( 1, Conv.To<int?>( "1" ) ); 666  } 667 
668         #endregion
669 
670         #region 目標爲Guid
671 
672         /// <summary>
673         ///通用泛型轉換,目標爲Guid,無效值 674         ///</summary>
675  [TestMethod] 676         public void TestTo_Guid_Invalid() { 677             Assert.AreEqual( Guid.Empty, Conv.To<Guid>( "1A" ) ); 678  } 679 
680         /// <summary>
681         ///通用泛型轉換,目標爲Guid,有效值 682         ///</summary>
683  [TestMethod] 684         public void TestTo_Guid() { 685             Assert.AreEqual( new Guid( "B9EB56E9-B720-40B4-9425-00483D311DDC" ), 686                 Conv.To<Guid>( "B9EB56E9-B720-40B4-9425-00483D311DDC" ) ); 687  } 688 
689         /// <summary>
690         ///通用泛型轉換,目標爲可空Guid,無效值 691         ///</summary>
692  [TestMethod] 693         public void TestTo_GuidOrNull_Invalid() { 694             Assert.IsNull( Conv.To<Guid?>( "1A" ) ); 695  } 696 
697         /// <summary>
698         ///通用泛型轉換,目標爲可空Guid,有效值 699         ///</summary>
700  [TestMethod] 701         public void TestTo_GuidOrNull() { 702             Assert.AreEqual( new Guid( "B9EB56E9-B720-40B4-9425-00483D311DDC" ), 703                 Conv.To<Guid?>( "B9EB56E9-B720-40B4-9425-00483D311DDC" ) ); 704  } 705 
706         #endregion
707 
708         #region 目標爲string
709 
710         /// <summary>
711         ///通用泛型轉換,目標爲string,有效值 712         ///</summary>
713  [TestMethod] 714         public void TestTo_String() { 715             Assert.AreEqual( "123", Conv.To<string>( 123 ) ); 716  } 717 
718         #endregion
719 
720         #region 目標爲double
721 
722         /// <summary>
723         ///通用泛型轉換,目標爲double,無效值 724         ///</summary>
725  [TestMethod] 726         public void TestTo_Double_Invalid() { 727             Assert.AreEqual( 0, Conv.To<double>( "1A" ) ); 728  } 729 
730         /// <summary>
731         ///通用泛型轉換,目標爲double,有效值 732         ///</summary>
733  [TestMethod] 734         public void TestTo_Double() { 735             Assert.AreEqual( 12.5, Conv.To<double>( "12.5" ) ); 736  } 737 
738         /// <summary>
739         ///通用泛型轉換,目標爲可空double,無效值 740         ///</summary>
741  [TestMethod] 742         public void TestTo_DoubleOrNull_Invalid() { 743             Assert.IsNull( Conv.To<double?>( "1A" ) ); 744  } 745 
746         /// <summary>
747         ///通用泛型轉換,目標爲可空double,有效值 748         ///</summary>
749  [TestMethod] 750         public void TestTo_DoubleOrNull() { 751             Assert.AreEqual( 12.5, Conv.To<double?>( "12.5" ) ); 752  } 753 
754         #endregion
755 
756         #region 目標爲decimal
757 
758         /// <summary>
759         ///通用泛型轉換,目標爲decimal,無效值 760         ///</summary>
761  [TestMethod] 762         public void TestTo_Decimal_Invalid() { 763             Assert.AreEqual( 0, Conv.To<decimal>( "1A" ) ); 764  } 765 
766         /// <summary>
767         ///通用泛型轉換,目標爲decimal,有效值 768         ///</summary>
769  [TestMethod] 770         public void TestTo_Decimal() { 771             Assert.AreEqual( 12.5M, Conv.To<decimal>( "12.5" ) ); 772  } 773 
774         /// <summary>
775         ///通用泛型轉換,目標爲可空decimal,無效值 776         ///</summary>
777  [TestMethod] 778         public void TestTo_DecimalOrNull_Invalid() { 779             Assert.IsNull( Conv.To<decimal?>( "1A" ) ); 780  } 781 
782         /// <summary>
783         ///通用泛型轉換,目標爲可空decimal,有效值 784         ///</summary>
785  [TestMethod] 786         public void TestTo_DecimalOrNull() { 787             Assert.AreEqual( 12.5M, Conv.To<decimal?>( "12.5" ) ); 788  } 789 
790         #endregion
791 
792         #region 目標爲bool
793 
794         /// <summary>
795         ///通用泛型轉換,目標爲bool,無效值 796         ///</summary>
797  [TestMethod] 798         public void TestTo_Bool_Invalid() { 799             Assert.AreEqual( false, Conv.To<bool>( "1A" ) ); 800  } 801 
802         /// <summary>
803         ///通用泛型轉換,目標爲bool,有效值 804         ///</summary>
805  [TestMethod] 806         public void TestTo_Bool() { 807             Assert.AreEqual( true, Conv.To<bool>( 1 ) ); 808  } 809 
810         /// <summary>
811         ///通用泛型轉換,目標爲可空bool,無效值 812         ///</summary>
813  [TestMethod] 814         public void TestTo_BoolOrNull_Invalid() { 815             Assert.IsNull( Conv.To<bool?>( "1A" ) ); 816  } 817 
818         /// <summary>
819         ///通用泛型轉換,目標爲可空bool,有效值 820         ///</summary>
821  [TestMethod] 822         public void TestTo_BoolOrNull() { 823             Assert.AreEqual( true, Conv.To<bool?>( "true" ) ); 824  } 825 
826         #endregion
827 
828         #region 目標爲DateTime
829 
830         /// <summary>
831         ///通用泛型轉換,目標爲DateTime,無效值 832         ///</summary>
833  [TestMethod] 834         public void TestTo_DateTime_Invalid() { 835             Assert.AreEqual( DateTime.MinValue, Conv.To<DateTime>( "1A" ) ); 836  } 837 
838         /// <summary>
839         ///通用泛型轉換,目標爲DateTime,有效值 840         ///</summary>
841  [TestMethod] 842         public void TestTo_DateTime() { 843             Assert.AreEqual( new DateTime( 2000, 1, 1 ), Conv.To<DateTime>( "2000-1-1" ) ); 844  } 845 
846         /// <summary>
847         ///通用泛型轉換,目標爲可空DateTime,無效值 848         ///</summary>
849  [TestMethod] 850         public void TestTo_DateTimeOrNull_Invalid() { 851             Assert.IsNull( Conv.To<DateTime?>( "1A" ) ); 852  } 853 
854         /// <summary>
855         ///通用泛型轉換,目標爲可空DateTime,有效值 856         ///</summary>
857  [TestMethod] 858         public void TestTo_DateTimeOrNull() { 859             Assert.AreEqual( new DateTime( 2000, 1, 1 ), Conv.To<DateTime?>( "2000-1-1" ) ); 860  } 861 
862         #endregion
863 
864         #endregion
865  } 866 }
ConvTest

  Conv類代碼以下。

 1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 
 5 namespace Util {  6     /// <summary>
 7     /// 類型轉換  8     /// </summary>
 9     public static class Conv {  10 
 11         #region 數值轉換
 12 
 13         /// <summary>
 14         /// 轉換爲整型  15         /// </summary>
 16         /// <param name="data">數據</param>
 17         public static int ToInt( object data ) {  18             if ( data == null )  19                 return 0;  20             int result;  21             var success = int.TryParse( data.ToString(), out result );  22             if ( success == true )  23                 return result;  24             try {  25                 return Convert.ToInt32( ToDouble( data, 0 ) );  26  }  27             catch ( Exception ) {  28                 return 0;  29  }  30  }  31 
 32         /// <summary>
 33         /// 轉換爲可空整型  34         /// </summary>
 35         /// <param name="data">數據</param>
 36         public static int? ToIntOrNull( object data ) {  37             if ( data == null )  38                 return null;  39             int result;  40             bool isValid = int.TryParse( data.ToString(), out result );  41             if ( isValid )  42                 return result;  43             return null;  44  }  45 
 46         /// <summary>
 47         /// 轉換爲雙精度浮點數  48         /// </summary>
 49         /// <param name="data">數據</param>
 50         public static double ToDouble( object data ) {  51             if ( data == null )  52                 return 0;  53             double result;  54             return double.TryParse( data.ToString(), out result ) ? result : 0;  55  }  56 
 57         /// <summary>
 58         /// 轉換爲雙精度浮點數,並按指定的小數位4舍5入  59         /// </summary>
 60         /// <param name="data">數據</param>
 61         /// <param name="digits">小數位數</param>
 62         public static double ToDouble( object data, int digits ) {  63             return Math.Round( ToDouble( data ), digits );  64  }  65 
 66         /// <summary>
 67         /// 轉換爲可空雙精度浮點數  68         /// </summary>
 69         /// <param name="data">數據</param>
 70         public static double? ToDoubleOrNull( object data ) {  71             if ( data == null )  72                 return null;  73             double result;  74             bool isValid = double.TryParse( data.ToString(), out result );  75             if ( isValid )  76                 return result;  77             return null;  78  }  79 
 80         /// <summary>
 81         /// 轉換爲高精度浮點數  82         /// </summary>
 83         /// <param name="data">數據</param>
 84         public static decimal ToDecimal( object data ) {  85             if ( data == null )  86                 return 0;  87             decimal result;  88             return decimal.TryParse( data.ToString(), out result ) ? result : 0;  89  }  90 
 91         /// <summary>
 92         /// 轉換爲高精度浮點數,並按指定的小數位4舍5入  93         /// </summary>
 94         /// <param name="data">數據</param>
 95         /// <param name="digits">小數位數</param>
 96         public static decimal ToDecimal( object data, int digits ) {  97             return Math.Round( ToDecimal( data ), digits );  98  }  99 
100         /// <summary>
101         /// 轉換爲可空高精度浮點數 102         /// </summary>
103         /// <param name="data">數據</param>
104         public static decimal? ToDecimalOrNull( object data ) { 105             if ( data == null ) 106                 return null; 107             decimal result; 108             bool isValid = decimal.TryParse( data.ToString(), out result ); 109             if ( isValid ) 110                 return result; 111             return null; 112  } 113 
114         /// <summary>
115         /// 轉換爲可空高精度浮點數,並按指定的小數位4舍5入 116         /// </summary>
117         /// <param name="data">數據</param>
118         /// <param name="digits">小數位數</param>
119         public static decimal? ToDecimalOrNull( object data, int digits ) { 120             var result = ToDecimalOrNull( data ); 121             if ( result == null ) 122                 return null; 123             return Math.Round( result.Value, digits ); 124  } 125 
126         #endregion
127 
128         #region Guid轉換
129 
130         /// <summary>
131         /// 轉換爲Guid 132         /// </summary>
133         /// <param name="data">數據</param>
134         public static Guid ToGuid( object data ) { 135             if ( data == null ) 136                 return Guid.Empty; 137  Guid result; 138             return Guid.TryParse( data.ToString(), out result ) ? result : Guid.Empty; 139  } 140 
141         /// <summary>
142         /// 轉換爲可空Guid 143         /// </summary>
144         /// <param name="data">數據</param>
145         public static Guid? ToGuidOrNull( object data ) { 146             if ( data == null ) 147                 return null; 148  Guid result; 149             bool isValid = Guid.TryParse( data.ToString(), out result ); 150             if ( isValid ) 151                 return result; 152             return null; 153  } 154 
155         /// <summary>
156         /// 轉換爲Guid集合 157         /// </summary>
158         /// <param name="guid">guid集合字符串,範例:83B0233C-A24F-49FD-8083-1337209EBC9A,EAB523C6-2FE7-47BE-89D5-C6D440C3033A</param>
159         public static List<Guid> ToGuidList( string guid ) { 160             var listGuid = new List<Guid>(); 161             if ( string.IsNullOrWhiteSpace( guid ) ) 162                 return listGuid; 163             var arrayGuid = guid.Split( ',' ); 164             listGuid.AddRange( from each in arrayGuid where !string.IsNullOrWhiteSpace( each ) select new Guid( each ) ); 165             return listGuid; 166  } 167 
168         #endregion
169 
170         #region 日期轉換
171 
172         /// <summary>
173         /// 轉換爲日期 174         /// </summary>
175         /// <param name="data">數據</param>
176         public static DateTime ToDate( object data ) { 177             if ( data == null ) 178                 return DateTime.MinValue; 179  DateTime result; 180             return DateTime.TryParse( data.ToString(), out result ) ? result : DateTime.MinValue; 181  } 182 
183         /// <summary>
184         /// 轉換爲可空日期 185         /// </summary>
186         /// <param name="data">數據</param>
187         public static DateTime? ToDateOrNull( object data ) { 188             if ( data == null ) 189                 return null; 190  DateTime result; 191             bool isValid = DateTime.TryParse( data.ToString(), out result ); 192             if ( isValid ) 193                 return result; 194             return null; 195  } 196 
197         #endregion
198 
199         #region 布爾轉換
200 
201         /// <summary>
202         /// 轉換爲布爾值 203         /// </summary>
204         /// <param name="data">數據</param>
205         public static bool ToBool( object data ) { 206             if ( data == null ) 207                 return false; 208             bool? value = GetBool( data ); 209             if ( value != null ) 210                 return value.Value; 211             bool result; 212             return bool.TryParse( data.ToString(), out result ) && result; 213  } 214 
215         /// <summary>
216         /// 獲取布爾值 217         /// </summary>
218         private static bool? GetBool( object data ) { 219             switch ( data.ToString().Trim().ToLower() ) { 220                 case "0": 221                     return false; 222                 case "1": 223                     return true; 224                 case "": 225                     return true; 226                 case "": 227                     return false; 228                 case "yes": 229                     return true; 230                 case "no": 231                     return false; 232                 default: 233                     return null; 234  } 235  } 236 
237         /// <summary>
238         /// 轉換爲可空布爾值 239         /// </summary>
240         /// <param name="data">數據</param>
241         public static bool? ToBoolOrNull( object data ) { 242             if ( data == null ) 243                 return null; 244             bool? value = GetBool( data ); 245             if ( value != null ) 246                 return value.Value; 247             bool result; 248             bool isValid = bool.TryParse( data.ToString(), out result ); 249             if ( isValid ) 250                 return result; 251             return null; 252  } 253 
254         #endregion
255 
256         #region 字符串轉換
257 
258         /// <summary>
259         /// 轉換爲字符串 260         /// </summary>
261         /// <param name="data">數據</param>
262         public static string ToString( object data ) { 263             return data == null ? string.Empty : data.ToString().Trim(); 264  } 265 
266         #endregion
267 
268         #region 通用轉換
269 
270         /// <summary>
271         /// 泛型轉換 272         /// </summary>
273         /// <typeparam name="T">目標類型</typeparam>
274         /// <param name="data">數據</param>
275         public static T To<T>( object data ) { 276             if ( data == null || string.IsNullOrWhiteSpace( data.ToString() ) ) 277                 return default( T ); 278             Type type = Nullable.GetUnderlyingType( typeof( T ) ) ?? typeof( T ); 279             try { 280                 if ( type.Name.ToLower() == "guid" ) 281                     return (T)(object)new Guid( data.ToString() ); 282                 if ( data is IConvertible ) 283                     return (T)Convert.ChangeType( data, type ); 284                 return (T)data; 285  } 286             catch { 287                 return default( T ); 288  } 289  } 290 
291         #endregion
292  } 293 }
Conv

  Conv公共操做類的用法,在單元測試中已經說得很清楚了,這也是單元測試的一個用途,即做爲API說明文檔。

  單元測試最強大的地方,多是可以幫助你迴歸測試,若是你發現個人代碼有BUG,請通知我一聲,我只須要在單元測試中增長一個測試來捕獲這個BUG,就能夠永久修復它,而且因爲採用TDD方式能夠得到很高的測試覆蓋率,因此我花上幾秒鐘運行一下所有測試,就能夠知道此次修改有沒有影響其它代碼。這也是你建立本身的應用程序框架所必需要作的,它能夠給你提供信心。

  能夠看到,我在單元測試中進行了不少邊界測試,好比參數爲null或空字符串等。但不可能窮舉全部可能出錯的狀況,由於可能想不到,另外時間有限,也不可能作到。當在項目上發現BUG後,再經過添加單元測試的方式修復BUG就能夠了。因爲你的項目代碼調用的是應用程序框架API,因此你只須要在框架內修復一次,項目代碼徹底不動。

  像數據類型轉換這樣簡單的操做,你發現寫單元測試很是容易,由於它有明確的返回值,但若是沒有返回值呢,甚至有外部依賴呢,那就沒有這麼簡單了,須要不少技巧,因此你多看幾本TDD和單元測試方面的著做有不少好處。

  另外,再補充一下,Conv這個類裏面有幾個法寶。一個是ToGuidList這個方法,當你須要把字符串轉換爲List<Guid>的時候就用它。還有一個泛型轉換的方法To<T>,不少時候能夠用它進行泛型轉換。

  最後,我把全部方法參數類型都改爲了object,主要是想使用起來方便一點,而不是隻支持字符串參數,這可能致使裝箱和拆箱,從而形成一些性能損失,不過個人大多數項目在性能方面尚未這麼高的要求,因此這個損失對我來說無關痛癢。

  還有些數據類型轉換,我沒有放進來,主要是我平時不多用到,當我用到時再增長。

  .Net應用程序框架交流QQ羣: 386092459,歡迎有興趣的朋友加入討論。

  謝謝你們的持續關注,個人博客地址:http://www.cnblogs.com/xiadao521/

  下載地址: http://files.cnblogs.com/xiadao521/Util.2014.11.12.1.rar

相關文章
相關標籤/搜索