zoukankan      html  css  js  c++  java
  • c# 扩展方法奇思妙用高级篇八:Type类扩展

    Type 类提供了大量的属性和方法,但在一些基础性开发工作中,Type类功能还有些欠缺,尤其上在处理泛型类型时,如可空类型和泛型集合类型。下面的类就针对这些地方进行扩展。

    扩展源码 

     1     public static class TypeHelper
     2     {
     3         public static bool IsNullableType(this Type type)
     4         {
     5             return (((type != null&& type.IsGenericType) && 
     6                 (type.GetGenericTypeDefinition() == typeof(Nullable<>)));
     7         }
     8 
     9         public static Type GetNonNullableType(this Type type)
    10         {
    11             if (IsNullableType(type))
    12             {
    13                 return type.GetGenericArguments()[0];
    14             }
    15             return type;
    16         }
    17 
    18         public static bool IsEnumerableType(this Type enumerableType)
    19         {
    20             return (FindGenericType(typeof(IEnumerable<>), enumerableType) != null);
    21         }
    22 
    23         public static Type GetElementType(this Type enumerableType)
    24         {
    25             Type type = FindGenericType(typeof(IEnumerable<>), enumerableType);
    26             if (type != null)
    27             {
    28                 return type.GetGenericArguments()[0];
    29             }
    30             return enumerableType;
    31         }
    32 
    33         public static bool IsKindOfGeneric(this Type type, Type definition)
    34         {
    35             return (FindGenericType(definition, type) != null);
    36         }
    37 
    38         public static Type FindGenericType(this Type definition, Type type)
    39         {
    40             while ((type != null&& (type != typeof(object)))
    41             {
    42                 if (type.IsGenericType && (type.GetGenericTypeDefinition() == definition))
    43                 {
    44                     return type;
    45                 }
    46                 if (definition.IsInterface)
    47                 {
    48                     foreach (Type type2 in type.GetInterfaces())
    49                     {
    50                         Type type3 = FindGenericType(definition, type2);
    51                         if (type3 != null)
    52                         {
    53                             return type3;
    54                         }
    55                     }
    56                 }
    57                 type = type.BaseType;
    58             }
    59             return null;
    60         }
    61     }

     从名字上就以大体知道方法的功能,下面是部分测试代码,帮助大家理解:

    测试代码 

     1     [TestMethod()]
     2     public void IsNullableTypeTest()
     3     {
     4         Assert.AreEqual(true, TypeExtension.IsNullableType(typeof(int?)));
     5         Assert.AreEqual(false, TypeExtension.IsNullableType(typeof(int)));
     6         Assert.AreEqual(true, TypeExtension.IsNullableType(typeof(Nullable<DateTime>)));
     7         Assert.AreEqual(false, TypeExtension.IsNullableType(typeof(DateTime)));
     8     }
     9     [TestMethod()]
    10     public void GetNonNullableTypeTest()
    11     {
    12         Assert.AreEqual(typeof(int), TypeExtension.GetNonNullableType(typeof(int?)));
    13         Assert.AreEqual(typeof(DateTime), TypeExtension.GetNonNullableType(typeof(Nullable<DateTime>)));
    14     }
    15     [TestMethod()]
    16     public void IsEnumerableTypeTest()
    17     {
    18         Assert.AreEqual(true, TypeExtension.IsEnumerableType(typeof(IEnumerable<string>)));
    19         Assert.AreEqual(true, TypeExtension.IsEnumerableType(typeof(Collection<int>)));
    20     }
    21     [TestMethod()]
    22     public void GetElementTypeTest()
    23     {
    24         Assert.AreEqual(typeof(int), TypeExtension.GetElementType(typeof(IEnumerable<int>)));
    25         Assert.AreEqual(typeof(DateTime), TypeExtension.GetElementType(typeof(Collection<DateTime>)));
    26     }
    27     [TestMethod()]
    28     public void IsKindOfGenericTest()
    29     {
    30         Assert.AreEqual(true, TypeExtension.IsKindOfGeneric(typeof(List<string>), typeof(IEnumerable<>)));
    31         Assert.AreEqual(true, TypeExtension.IsKindOfGeneric(typeof(string), typeof(IComparable<>)));
    32     }
    33     [TestMethod()]
    34     public void FindGenericTypeTest()
    35     {
    36         Assert.AreEqual(typeof(IEnumerable<string>),
    37         TypeExtension.FindGenericType(typeof(IEnumerable<>), typeof(List<string>)));
    38     }

     代码就是最好的文档,想必大家已经都看明白了。

    TypeHelper 是我从一个类库中提取的,它原本是一个 internal static class,内部的方法同样 internal static 。我仅仅是把 internal 改成了 public ,并在每个方法的第一个参数前加了个 this,最后给类中的方法按从简到难的顺序进行了排序。

    也许是因为 TypeHelper 是一个内部类,并有强烈的应用语境,TypeHelper 并没有采用契约式编程的方式,甚至在命名上也做了一些省略: 如 IsEnumerableType、GetElementType 两个方法是实际是用来处理泛型集合类型的,但在方法名和参数名上并没有“Generic”的字眼。(如果传入非泛型类型或其它类型,将会产生难以预料的结果或异常。)

    像这样简单将内部静态类 TypeHelper 中的静态方法公开为扩展方法是存在问题的,所以在应用之前,还得再做些工作。改进成为契约式编程的方式并不难,难的是给扩展方法起一个清晰明了简单易懂的名字,否则就不要扩展了。IsEnumerableType、GetElementType 应该体现出是对泛型集合进行操作,简单加上Generic字样后名字好长,也不好理解。(大家如果能想出好的名字,请发在回复中,不胜感激!)

    补充

    另外在使用时,我发现两处“奇怪”的地方,如下图:

    TypeExtension

    调试至此处,type1为空,type2则是一个少见的奇怪类型。

    TypeHelper 的出处我会在下一篇随笔中进行说明。

    本人系列文章《c#扩展方法奇思妙用》,敬请关注!

  • 相关阅读:
    二叉树的非递归遍历
    关于vc变量定义顺序猜测
    单点登录详解(token简述)(七)
    session及cookie详解(七)
    dubbo(八)
    Zookeeper简介(九)
    拦截器与过滤器的区别(九)
    cookie详解(八)
    kafka可视化工具(二)
    Windows环境安装kafka(一)
  • 原文地址:https://www.cnblogs.com/ldp615/p/TypeExtension.html
Copyright © 2011-2022 走看看