接着《浅谈.Net反射 4》文章里面的代码,我们继续。
如何进一步查看类型信息?
获取类型基本信息,定义TypeExplore:
public static void TypeExplore(Type t)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("TypeName:");
sb.AppendLine("Name: " + t.Name);
sb.AppendLine("FullName: " + t.FullName);
sb.AppendLine("Namespace: " + t.Namespace);
sb.AppendLine("other info:");
sb.AppendLine("BaseType: " + t.BaseType);
sb.AppendLine("UnderlyingSystemType: " + t.UnderlyingSystemType);
sb.AppendLine("Type info:");
sb.AppendLine("Attributes: " + t.Attributes);
sb.AppendLine("IsValueType: " + t.IsValueType);
sb.AppendLine("IsEnum: " + t.IsEnum);
sb.AppendLine("IsClass: " + t.IsClass);
sb.AppendLine("IsArray: " + t.IsArray);
sb.AppendLine("IsInterface: " + t.IsInterface);
sb.AppendLine("IsPointer: " + t.IsPointer);
sb.AppendLine("IsSealed: " + t.IsSealed);
sb.AppendLine("IsPrimitive: " + t.IsPrimitive);
sb.AppendLine("IsAbstract: " + t.IsAbstract);
sb.AppendLine("IsPublic: " + t.IsPublic);
sb.AppendLine("IsNotPublic: " + t.IsNotPublic);
sb.AppendLine("IsVisible: " + t.IsVisible);
sb.AppendLine("IsByRef: " + t.IsByRef);
Console.WriteLine(sb.ToString());
}
运行下面的代码:
Type t = typeof(DemoClass);
TypeExplore(t);
运行结果:
值得注意的是Attributes属性,它返回一个TypeAttributes位标记,这个标记标识了类型的一些元信息,可以看到熟悉的Class、Public、Sealed。相应的,IsClass、IsSealed、IsPublic等属性也返回为True。
成员信息与MemberInfo类型
对于一个类型而言,可能会包含哪些成员?常见的有字段、属性、方法、构造函数、接口、嵌套类型等。MemberInfo类代表着Type的成员类型,值得注意的是Type类本身又继承自MemberInfo类,因为一个类型经常也是另一类型的成员。
Type类提供了GetMembers()、GetMember()、FindMember()等方法用于获取某个成员类型。
添加一个方法MemberExplore():
public static void MemberExplore(Type t)
{
StringBuilder sb = new StringBuilder();
MemberInfo[] memberInfo = t.GetMembers();
sb.Append("Type " + t.Name + " member info:\n");
foreach (MemberInfo mi in memberInfo)
{
sb.AppendLine("memberInfo: " + mi.ToString().PadRight(40) + " memberType: " + mi.MemberType);
}
Console.WriteLine(sb.ToString());
}
运行下面的代码:
Type t = typeof(DemoClass);
MemberExplore(t);
运行结果:
MemberExplore()方法在Type的实例上调用了GetMembers()方法获取了成员信息的一个数组,然后遍历了数组,打印了成员的名称和类型。注意到Name属性在编译后变为了get_Name()和set_Name()两个独立的方法;myEvent事件的注册(+=)和取消注册(-=)分别成为了add_myEvent()和remove_myEvent方法。同时,发现私有字段name没有被打印出来,而基类System.Object的成员GetType()和Equals()被打印了出来。
有的时候,可能不希望查看基类的成员,也可能需要查看私有的成员,此时可以使用GetMembers()的重载方法,传入BindingFlags位标记作为参数来完成。
BindingFlags位标记对如何获取成员的方式进行控制(也可以控制如何创建对象实例)。对于本例,如果想获取所有的公有、私有、静态、实例成员,那么只需要像下面这样修改GetMembers()方法就可以了。
MemberInfo[] memberInfo = t.GetMembers(
BindingFlags.Public |
BindingFlags.Static |
BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.DeclaredOnly
);
我们看一下Type类中的GetMember和GetMembers的方法签名:
public MemberInfo[] GetMember(string name)
public virtual MemberInfo[] GetMember(string name, BindingFlags bindingAttr)
public virtual MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
public MemberInfo[] GetMembers()
public abstract MemberInfo[] GetMembers(BindingFlags bindingAttr);
还有一个FindMembers方法:
public virtual MemberInfo[] FindMembers(MemberTypes memberType, BindingFlags bindingAttr, MemberFilter filter, object filterCriteria)
FindMembers可以根据MemberTypes进行查找Members信息。如果想要获取所有的方法(Method),那么可以调用Type类的FindMembers()方法:
BindingFlags flags = BindingFlags.Public |
BindingFlags.Static |
BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.DeclaredOnly;
MemberInfo[] memberInfo = t.FindMembers(
MemberTypes.Method, // 说明查找的成员类型为 Method
flags,
Type.FilterName,
"*"
);
MemberInfo类有两个属性值得注意,一个是DeclaringType,一个是ReflectedType,返回的都是Type类型。
DeclaredType返回的是声明该成员的类型,即可以知道该成员是定义在哪一个类里面的。例如继承自System.Object基类的Equals()方法,对于Equals()方法来说,它的DeclaringType返回的对象相当于是typeof(System.Object),因为它是在System.Object中被定义的。
而Equals()方法的ReflectedType返回的对象则相当于是typeof(DemoClass),因为它是通过DemoClass的类型实例被获取到的。
本文回顾:
类型基本信息
成员信息与MemberInfo类型