Util應用程序框架公共操作類(三):數據類型轉換公共操作類(擴展篇)


  上一篇以TDD方式介紹了數據類型轉換公共操作類的開發,並提供了單元測試和實現代碼,本文將演示通過擴展方法來增強公共操作類,以便調用時更加簡化。

  下面以字符串轉換為List<Guid>為例進行討論。

string input = "83B0233C-A24F-49FD-8083-1337209EBC9A,EAB523C6-2FE7-47BE-89D5-C6D440C3033A"; var result = Util.Conv.ToGuidList( input );

  觀察上面的代碼,它確實已經被封裝起來了,通過一個明確的API進行調用。不過它是最簡化形式嗎?

  在.Net 3.0提供了一個擴展方法的語法,這是一個非常強大的功能,它通過靜態方法的方式向目標類型添加一個模擬的實例方法。

  上面例子就被簡化成如下形式。

string input = "83B0233C-A24F-49FD-8083-1337209EBC9A,EAB523C6-2FE7-47BE-89D5-C6D440C3033A"; var result = input.ToGuidList();

  這樣在調用的時候就會更爽,從而幫助我們在項目開發過程中進一步減輕負擔。

  下面在Util.Tests單元測試項目中添加一個Extensions文件夾,並在Extensions文件夾中添加ConvertExtensionTest.cs的文件,類名為ConvertExtensionTest,用來測試類型轉換擴展。

  ConvertExtensionTest代碼如下。

 1 using System;  2 using System.Collections.Generic;  3 using Microsoft.VisualStudio.TestTools.UnitTesting;  4 
 5 namespace Util.Tests.Extensions {  6     /// <summary>
 7     /// 類型轉換擴展測試  8     /// </summary>
 9  [TestClass]  10     public class ConvertExtensionTest {  11         /// <summary>
 12         /// 轉換為整數  13         /// </summary>
 14  [TestMethod]  15         public void TestToInt() {  16             string obj1 = "";  17             string obj2 = "1";  18             Assert.AreEqual( 0, obj1.ToInt() );  19             Assert.AreEqual( 1, obj2.ToInt() );  20  }  21 
 22         /// <summary>
 23         /// 轉換為可空整數  24         /// </summary>
 25  [TestMethod]  26         public void TestToIntOrNull() {  27             string obj1 = "";  28             string obj2 = "1";  29  Assert.IsNull( obj1.ToIntOrNull() );  30             Assert.AreEqual( 1, obj2.ToIntOrNull() );  31  }  32 
 33         /// <summary>
 34         /// 轉換為雙精度浮點數  35         /// </summary>
 36  [TestMethod]  37         public void TestToDouble() {  38             string obj1 = "";  39             string obj2 = "1.2";  40             Assert.AreEqual( 0, obj1.ToDouble() );  41             Assert.AreEqual( 1.2, obj2.ToDouble() );  42  }  43 
 44         /// <summary>
 45         /// 轉換為可空雙精度浮點數  46         /// </summary>
 47  [TestMethod]  48         public void TestToDoubleOrNull() {  49             string obj1 = "";  50             string obj2 = "1.2";  51  Assert.IsNull( obj1.ToDoubleOrNull() );  52             Assert.AreEqual( 1.2, obj2.ToDoubleOrNull() );  53  }  54 
 55         /// <summary>
 56         /// 轉換為高精度浮點數  57         /// </summary>
 58  [TestMethod]  59         public void TestToDecimal() {  60             string obj1 = "";  61             string obj2 = "1.2";  62             Assert.AreEqual( 0, obj1.ToDecimal() );  63             Assert.AreEqual( 1.2M, obj2.ToDecimal() );  64  }  65 
 66         /// <summary>
 67         /// 轉換為可空高精度浮點數  68         /// </summary>
 69  [TestMethod]  70         public void TestToDecimalOrNull() {  71             string obj1 = "";  72             string obj2 = "1.2";  73  Assert.IsNull( obj1.ToDecimalOrNull() );  74             Assert.AreEqual( 1.2M, obj2.ToDecimalOrNull() );  75  }  76 
 77         /// <summary>
 78         /// 轉換為日期  79         /// </summary>
 80  [TestMethod]  81         public void TestToDate() {  82             string obj1 = "";  83             string obj2 = "2000-1-1";  84  Assert.AreEqual( DateTime.MinValue, obj1.ToDate() );  85             Assert.AreEqual( new DateTime( 2000, 1, 1 ), obj2.ToDate() );  86  }  87 
 88         /// <summary>
 89         /// 轉換為可空日期  90         /// </summary>
 91  [TestMethod]  92         public void TestToDateOrNull() {  93             string obj1 = "";  94             string obj2 = "2000-1-1";  95  Assert.IsNull( obj1.ToDateOrNull() );  96             Assert.AreEqual( new DateTime( 2000, 1, 1 ), obj2.ToDateOrNull() );  97  }  98 
 99         /// <summary>
100         /// 轉換為Guid 101         /// </summary>
102  [TestMethod] 103         public void TestToGuid() { 104             string obj1 = ""; 105             string obj2 = "B9EB56E9-B720-40B4-9425-00483D311DDC"; 106  Assert.AreEqual( Guid.Empty, obj1.ToGuid() ); 107             Assert.AreEqual( new Guid( obj2 ), obj2.ToGuid() ); 108  } 109 
110         /// <summary>
111         /// 轉換為可空Guid 112         /// </summary>
113  [TestMethod] 114         public void TestToGuidOrNull() { 115             string obj1 = ""; 116             string obj2 = "B9EB56E9-B720-40B4-9425-00483D311DDC"; 117  Assert.IsNull( obj1.ToGuidOrNull() ); 118             Assert.AreEqual( new Guid( obj2 ), obj2.ToGuidOrNull() ); 119  } 120 
121         /// <summary>
122         /// 轉換為Guid集合,值為字符串 123         /// </summary>
124  [TestMethod] 125         public void TestToGuidList_String() { 126             const string guid = "83B0233C-A24F-49FD-8083-1337209EBC9A,,EAB523C6-2FE7-47BE-89D5-C6D440C3033A,"; 127             Assert.AreEqual( 2, guid.ToGuidList().Count ); 128             Assert.AreEqual( new Guid( "83B0233C-A24F-49FD-8083-1337209EBC9A" ), guid.ToGuidList()[0] ); 129             Assert.AreEqual( new Guid( "EAB523C6-2FE7-47BE-89D5-C6D440C3033A" ), guid.ToGuidList()[1] ); 130  } 131 
132         /// <summary>
133         /// 轉換為Guid集合,值為字符串集合 134         /// </summary>
135  [TestMethod] 136         public void TestToGuidList_StringList() { 137             var list = new List<string> {"83B0233C-A24F-49FD-8083-1337209EBC9A", "EAB523C6-2FE7-47BE-89D5-C6D440C3033A"}; 138             Assert.AreEqual( 2, list.ToGuidList().Count ); 139             Assert.AreEqual( new Guid( "83B0233C-A24F-49FD-8083-1337209EBC9A" ), list.ToGuidList()[0] ); 140             Assert.AreEqual( new Guid( "EAB523C6-2FE7-47BE-89D5-C6D440C3033A" ), list.ToGuidList()[1] ); 141  } 142 
143         /// <summary>
144         /// 轉換為字符串 145         /// </summary>
146  [TestMethod] 147         public void TestToStr() { 148             object value = null; 149             Assert.AreEqual( string.Empty, value.ToStr() ); 150             value = 1; 151             Assert.AreEqual( "1", value.ToStr() ); 152  } 153  } 154 }

  在Util類庫項目中,添加Extensions.Convert.cs文件,類名為Extensions,它是一個靜態類,這是擴展方法的強制要求,並且它還是一個部分類,這是因為以后需要進行擴展時,就可以在Extensions類中繼續擴展其它功能。

  Extensions.Convert.cs中的代碼如下。

using System; using System.Collections.Generic; using System.Linq; namespace Util { /// <summary>
    /// 類型轉換擴展 /// </summary>
    public static partial class Extensions { /// <summary>
        /// 轉換為int /// </summary>
        /// <param name="data">數據</param>
        public static int ToInt( this string data ) { return Conv.ToInt( data ); } /// <summary>
        /// 轉換為可空int /// </summary>
        /// <param name="data">數據</param>
        public static int? ToIntOrNull( this string data ) { return Conv.ToIntOrNull( data ); } /// <summary>
        /// 轉換為double /// </summary>
        /// <param name="data">數據</param>
        public static double ToDouble( this string data ) { return Conv.ToDouble( data ); } /// <summary>
        /// 轉換為可空double /// </summary>
        /// <param name="data">數據</param>
        public static double? ToDoubleOrNull( this string data ) { return Conv.ToDoubleOrNull( data ); } /// <summary>
        /// 轉換為decimal /// </summary>
        /// <param name="data">數據</param>
        public static decimal ToDecimal( this string data ) { return Conv.ToDecimal( data ); } /// <summary>
        /// 轉換為可空decimal /// </summary>
        /// <param name="data">數據</param>
        public static decimal? ToDecimalOrNull( this string data ) { return Conv.ToDecimalOrNull( data ); } /// <summary>
        /// 轉換為日期 /// </summary>
        /// <param name="data">數據</param>
        public static DateTime ToDate( this string data ) { return Conv.ToDate( data ); } /// <summary>
        /// 轉換為可空日期 /// </summary>
        /// <param name="data">數據</param>
        public static DateTime? ToDateOrNull( this string data ) { return Conv.ToDateOrNull( data ); } /// <summary>
        /// 轉換為Guid /// </summary>
        /// <param name="data">數據</param>
        public static Guid ToGuid( this string data ) { return Conv.ToGuid( data ); } /// <summary>
        /// 轉換為可空Guid /// </summary>
        /// <param name="data">數據</param>
        public static Guid? ToGuidOrNull( this string data ) { return Conv.ToGuidOrNull( data ); } /// <summary>
        /// 轉換為Guid集合 /// </summary>
        /// <param name="data">數據,范例: "83B0233C-A24F-49FD-8083-1337209EBC9A,EAB523C6-2FE7-47BE-89D5-C6D440C3033A"</param>
        public static List<Guid> ToGuidList( this string data ) { return Conv.ToGuidList( data ); } /// <summary>
        /// 轉換為Guid集合 /// </summary>
        /// <param name="data">字符串集合</param>
        public static List<Guid> ToGuidList( this IList<string> data ) { if ( data == null ) return new List<Guid>(); return data.Select( t => t.ToGuid() ).ToList(); } /// <summary>
        /// 獲取字符串 /// </summary>
        /// <param name="data">對象</param>
        public static string ToStr( this object data ) { return Conv.ToString( data ); } } }

  為了避免代碼冗余,在數據類型擴展類中,會將調用委托給conv進行處理,而不是在擴展類中重新實現一次。

  擴展方法的一個弊端是可能污染原生的.Net環境,從而導致混亂,特別是在擴展object對象時要十分小心,因為會添加到每個對象中。從我提供的示例代碼可以看到,我主要是在string對象上擴展,因為這樣范圍會小得多。

  對於是否會濫用擴展方法,我的建議是如果你的應用程序框架使用范圍很小,那么不必理會其它人的看法,使勁擴展直至你自己都覺得負擔重重,然后再進行減肥。但是,當框架使用范圍比較大,應該盡量不污染系統原生類,因為很多程序員在代碼提示中找到這些API后,可能在不了解的情況下胡亂調用導致BUG,且由於使用范圍大,框架創建人不能及時糾正其它人的問題。

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

  謝謝大家的持續關注,我的博客地址:http://www.cnblogs.com/xiadao521/

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM