来自:http://www.cnblogs.com/mgen/archive/2012/06/24/2560234.html
先说类型中成员的枚举,传统的Type类型的成员枚举会返回public,static或者非static的成员,这个可以由BindingFlags枚举设置,因此无论是枚举全部成员还是根据名称返回一个成员,甚至是用Type来限制类型,默认的BindingFlags是这样的:
BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public
在.NET 4.5中,加入了另一种快捷的方法(当然在.NET 4.5之前也可以这样做,只不过需要手动设置BindingFlags),通过使用System.Reflection中RuntimeReflectionExtensions类型提供的扩展方法,返回的成员是这样类型的:
BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic
可以看到,NonPublic类型被加入。也就是私有成员也会被返回。
RuntimeReflectionExtensions的方法命名都是GetRuntimeXXX的方式。当然也有一些方法跟BindingFlags没有关系,比如GetMethodInfo就是返回Delegate.Method属性。
同时RuntimeReflectionExtensions的方法都会确定Type类型是RuntimeType类型,否则会抛出ArgumentException,同时RuntimeReflectionExtensions.GetRuntimeBaseDefinition方法还会验证MethodInfo是RuntimeMethodInfo类型。
.NET 4.5还有另一种成员枚举的方法,通过一个新的类型,同样在System.Reflection命名空间中,他是TypeInfo类型。TypeInfo类型影响了.NET 4.5中的类型的执行。首先一个新接口:IReflectableType,只有一个方法,GetTypeInfo返回一个TypeInfo对象。其实IReflectableType类型或多或少有点像.NET 4.5之前的IReflect接口。
他有一个执行类,就是TypeInfo类型本身:
TypeInfo类型继承自Type,然后执行IReflectableType,他的GetTypeInfo方法的执行就是返回自己。如下,TypeInfo类型的定义:
//在System.Reflection
public abstract class TypeInfo : Type, IReflectableType
最后内部的RuntimeType类继承关系也改变了,.NET 4.5之前是继承自Type类型,而.NET 4.5中他是继承自TypeInfo类型,当然仍然间接继承自Type类型。
internal class RuntimeType : TypeInfo, ISerializable, ICloneable
而TypeInfo也提供了类似上述模式的类型成员返回或者说枚举方式,但是它内部使用的BindingFlags是:
BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public |BindingFlags.NonPublic
相比RuntimeRefelctionExtensions,增加了DeclaredOnly,也就是说只有定义的成员才会被返回。
因此TypeInfo的方法都是类似GetDeclaredXXX的命名:
TypeInfo同时定义其他辅助方法,比如AsType把自己重新转换成Type(当然子类往父类的转换本来就是隐世的,可以能为了方便去掉其相关的扩展方法?),还有常用的IsAssignableFrom,可以直接和另一个TypeInfo做比较。
那么怎样从Type获取TypeInfo呢?简单,判断Type是否执行IReflectable,是的话,返回IReflectable.GetTypeInfo。当然,这个步骤在.NET 4.5已经有了扩展方法的定义,在RuntimeReflectionExtensions.GetTypeInfo方法中。
OK,写了这么多,来练习一下,定义两个非常简单的有继承关系的类型:
//b继承a,每一个类型内有一个public属性和private属性
class a
{
public int Prop1 { get; set; }
int PrivateProp1 { get; set; }
}
class b: a
{
public int Prop2 { get; set; }
int PrivateProp2 { get; set; }
}
注意加入System.Reflection命名空间,这样所有扩展方法能工作:
using System.Reflection;
好,首先用最传统方法:
foreach(var pi in typeof(b).GetProperties())
Console.WriteLine(pi.Name);
类型b的所有公共成员会被输出:
Prop2
Prop1
第二种方法,通过RuntimeReflectionExtensions.GetRuntimeProperties方法。
//通过RuntimeReflectionExtensions.GetRuntimeProperties
foreach(var pi in typeof(b).GetRuntimeProperties())
Console.WriteLine(pi.Name);
b类型的所有成员会被输出:
Prop2
PrivateProp2
Prop1
最后就是通过TypeInfo:
//通过TypeInfo
foreach (var pi in typeof(b).GetTypeInfo().DeclaredProperties)
Console.WriteLine(pi.Name);
b类型的所有本类定义的属性会被显示:
Prop2
PrivateProp2
作者:Mgen
出处:www.cnblogs.com/mgen
其他参考页面:我的软件和工程,博客导读。