在反射和泛型中經常會使用到Type類,獲取Type的最常用的方法是 obj.GetType(),和typeof(T)。在獲取泛型的type時有些小坑。
1 public static void Main(string[] args) 2 { 3 A a = new B 4 { 5 a = "a", 6 b = "b", 7 c = "c", 8 }; 9 B c = new B 10 { 11 a = "a", 12 b = "b", 13 c = "c", 14 }; 15 put(a); 16 put<A>(c); 17 put<B>(c); 18 put<IC>(c); 19 Console.ReadLine(); 20 } 21 public static void put<T>(T t) 22 { 23 24 Type type1 = typeof(T); 25 Console.WriteLine(); 26 Console.WriteLine("****************typeof*******************************"); 27 foreach (var item in type1.GetProperties()) 28 { 29 string name = item.Name; 30 string value = item.GetValue(t).ToString(); 31 Console.WriteLine("name=" + name + ",value=" + value); 32 } 33 Console.WriteLine("****************GetType*******************************"); 34 Type type2 = t.GetType(); 35 36 foreach (var item in type2.GetProperties()) 37 { 38 string name = item.Name; 39 string value = item.GetValue(t).ToString(); 40 Console.WriteLine("name=" + name + ",value=" + value); 41 } 42 43 } 44 45 public class A 46 { 47 public string a { get; set; } 48 } 49 public interface IC 50 { 51 string c { get; set; } 52 } 53 public class B : A,IC 54 { 55 public string c { get; set; } 56 public string b { get; set; } 57 }
在看看代碼的執行結果:
發現一個問題 GetType 和typeof的結果不一樣。put<T>(T t) 顯而易見,在傳入相同的對象不同泛型 t.GetType()的返回值是確定的,而typeof(T)是可以變化的。obj.GetType()和定義obj的類型沒有直接的關系,它的返回值是 YYYY obj = new XXXX() ; XXXX的類型,不一定是YYYY的類型。typeof就不用多說了
所以在此處代碼應該寫typeof(T),而不是t.GetType(),不然就失去泛型的意思。
GetType()有什么妙用的,我們來看下一段代碼:
1 public static void Main(string[] args) 2 { 3 D d = new D 4 { 5 a = "a", 6 b = 1, 7 d1 = new D1 { d1 = 1 }, 8 time = DateTime.Now, 9 }; 10 put2(d); 11 Console.ReadLine(); 12 } 13 public static void put2<T>(T t) 14 { 15 Type type1 = typeof(T); 16 Console.WriteLine(); 17 PropertyInfo[] Properties = type1.GetProperties(); 18 19 foreach (PropertyInfo item in Properties) 20 { 21 Console.WriteLine(item.GetType().FullName); 22 string name = item.Name; 23 object value = item.GetValue(t); 24 25 Console.WriteLine("參數的命名空間為:" +value.GetType().FullName); 26 Console.WriteLine("name=" + name + ",value=" + value.ToString()); 27 } 28 } 29 public class D 30 { 31 public string a { get; set; } 32 public int b { get; set; } 33 public DateTime time { get; set; } 34 private string c { get; set; } 35 public D1 d1 { get; set; } 36 37 } 38 public class D1 39 { 40 public int d1 { get; set; } 41 public override string ToString() 42 { 43 return d1.ToString(); 44 } 45 }
這段代碼輸出為:
這段代碼的21行是輸出item的命名空間,結果卻是RuntimePropertyInfio不是定義的PropertyInfio。並且RuntimePropertyInfio這個類是不可以訪問的。簡單的推測出RuntimePropertyInfio 類的修飾詞可能是private或者是internal,而且這個類是繼承了PropertyInfio,同時也能推測出繼承PropertyInfio的類絕對不是這一種。這個是c#源碼中常用的一些手段。
再來看item.getValue(t)中 在源碼中的返回值是object,
而我們卻而已通過GetType() 獲得類具體的命名空間,通過這些方法就可以處理不用的參數。