欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C# 类型反射

程序员文章站 2022-07-15 09:56:05
...

反射
反射(reflection)是一个运行库类型发现的过程。与其他命名空间一样,System.Reflection
包含了大量相关类型;
C# 类型反射
为了说明反射的基本过程,建立一个名为MyTypeViewer的控制台程序,这个程序将显示[mscorlib.dll]和MyTypeViewer中类型的方法、属性、字段和支持的接口,创建好这个应用程序后,还要确保引用System.Reflection命名空间。

// 需要为反射导入泛型命名空间
using System.Reflection;

反射的方法
修饰Program类,定义一些静态方法,每个都带有一个System.Type参数并返回void类型。首先,编写ListMethods()方法。注意Type.GetMethods()如何返回一个System.Reflection.MethodInfo类型的数组,它使用标准的foreach循环枚举,如下所示:

  // 显示类型的方法名称
 static void ListMethods(Type t)
  {
      Console.WriteLine("***** Methods *****");
      MethodInfo[] mi = t.GetMethods();
      foreach (MethodInfo m in mi) {
          Console.WriteLine("-> {0}", m.Name);
      }
      Console.WriteLine();
  }

这里,只是使用MethodInfo.Name属性输出方法的名称,此外MethodInfo有许多其他成员可以决定方法是否静态的、虚拟的、泛型的或抽象的,不仅如此,使用MethodInfo类型还能够获取方法的返回值和参数集。
反射字段和属性
还有一个与ListMethods()的实现非常相似就是ListFields(),不过注意不同的是:ListFields()调用了Type.GetFields()并且它的返回值是FieldInfo数组。为了说明一下,
就使用LINQ查询只输出了每个字段的名称。

static void ListFields(Type t)
        {
            Console.WriteLine("***** Fields *****");
            var fieldNames = from f in t.GetFields() select f.Name;
            foreach (var name in fieldNames) {
                Console.WriteLine("->{0}", name);
            }
            Console.WriteLine();
        }
        // 显示类型的属性名称
        static void ListProps(Type t)
        {
            Console.WriteLine("***** Properties ******");
            var propNames = from p in t.GetProperties() select p.Name;
            foreach (var name in propNames) {
                Console.WriteLine("-> {0}", name);
            }
            Console.WriteLine();
        }

反射实现的接口
建立一个名为ListInterfaces()的方法,它将输出传入类型支持所有的接口名称。注意:对GetInterfaces()的调用返回一个System.Type类型的数组。

 // 显示实现的接口
 static void ListInterfaces(Type t)
 {
     Console.WriteLine("***** Interfaces ******");
     var ifaces = from i in t.GetInterfaces() select i;
     foreach (Type i in ifaces)
     {
         Console.WriteLine("->{0}", i.Name);
     }
 }

说明:System.Type中的大多数get方法(GetMethods()、GetInterfaces()等)都包含指定BindingFlags枚举值得重载,可以对搜索的内容进行较大的的控制。
实现Main()方法

static void Main(string[] args)
        {
            Console.WriteLine("***** Welcome to MyTypeViewer *****");
            string typeName = "";

            do
            {
                Console.WriteLine("\nEnter a type name to evaluate");
                Console.WriteLine("or enter Q to quit: ");

                // 得到类型的名称
                typeName = Console.ReadLine();

                // 询问用户是否想退出
                if (typeName.ToUpper() == "Q")
                {
                    break;
                }

                // 测试显示类型
                try
                {
                    Type t = Type.GetType(typeName);
                    Console.WriteLine("");
                    ListFields(t);
                    ListProps(t);
                    ListMethods(t);
                    ListInterfaces(t);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Sorry,Can't find type");
                }
            } while (true);
        }

启动项目运行,控制台输出的结果如下:
C# 类型反射