zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    每日leetcode-数组-387. 字符串中的第一个唯一字符
    每日leetcode-数组-541. 反转字符串 II
    每日leetcode-数组-344. 反转字符串
    每日leetcode-数组-58. 最后一个单词的长度
    每日leetcode-数组-434. 字符串中的单词数
    每日leetcode-数组-14. 最长公共前缀
    每日leetcode-数组-125. 验证回文串
    每日leetcode-数组-520. 检测大写字母
    Weblogic漏洞挖矿病毒解决方法
    C盘空间不足清理
  • 原文地址:https://www.cnblogs.com/xiadao521/p/4094812.html
Copyright © 2011-2022 走看看