浅谈.Net反射 6

接着《浅谈.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类型

本文分享自微信公众号 - 明丰随笔(liumingfengwx2)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-07-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券