在反射和泛型中经常会使用到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 B10 {11 a = "a",12 b = "b",13 c = "c",14 };15 put(a);16 put(c);17 put(c);18 put(c);19 Console.ReadLine();20 }21 public static void put (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 A46 {47 public string a { get; set; }48 }49 public interface IC50 {51 string c { get; set; }52 }53 public class B : A,IC54 {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)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 D30 {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 D139 {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() 获得类具体的命名空间,通过这些方法就可以处理不用的参数。