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#扩展方法奇思妙用》,敬请关注!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值