程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> c#擴展方法奇思妙用高級篇八:Type類擴展

c#擴展方法奇思妙用高級篇八:Type類擴展

編輯:關於C語言

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字樣後名字好長,也不好理解。(大家如果能想出好的名字,請發在回復中,不勝感激!)

另外在使用時,我發現兩處“奇怪”的地方,如下圖:

調試至此處,type1為空,type2則是一個少見的奇怪類型。

TypeHelper 的出處我會在下一篇隨筆中進行說明。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved