zoukankan      html  css  js  c++  java
  • 学习系列之反射

    一 反射概述

         反射是一种机制,通过这种机制我们可以知道一个未知类型的类型信息.比如,有一个对象a,这个对象不是我们定义的,也许是通过网络捕捉到的,也许是使用泛型定义的,但我们想知道这个对象的类型信息,想知道这个对象有哪些方法或者属性什么的.甚至我们想进一步调用这个对象的方法.关键是现在我们只知道它是一个对象,不知道它的类型,自然不会知道它有哪些方法等信息.这时我们该怎么办?反射机制就是解决这么一个问题的.通过反射机制我们可以知道未知类型对象的类型信息,并且使用它 

      ·  通过反射可以提供类型信息,从而使得我们开发人员在运行时能够利用这些信息构造和使用对象。 

      ·  反射机制允许程序在执行过程中动态地添加各种功能。

    二 反射的核心类:System.Type类

    • 许多支持反射的类都位于System.Reflection命名空间中,他们是.net  Reflection API的一部分,所以在使用的反射的程序中一般都要使用 System.Reflection的命名空间。
    • System. Type类包装了类型,因此是整个反射子系统的核心,这个类中包含了很多属性和方法,使用这些属性和方法可以在运行时得到类型的信息。
    • Type类派生于System.Reflection.MemberInfo抽象类   

          注意: 

    • MemberType属性的返回类型为MemberTypes,这是一个枚举,它定义了用于表示不同成员的类型值。这些值包括:  MemberTypes.Constructor, MemberTypes.Method,     MemberTypes.Field,   MemberTypes.Event,  MemberTypes.Property。因此可以通过检查MemberType属性来确定成员的类型,例如,在MemberType属性的值为MemberTypes.Method时,该成员为方法
    • MemberInfo类还包含两个与特性相关的抽象方法:  

            GetCustomAttributes() :获得与主调对象关联的自定义特性列表。

            IsDefined(): 确定是否为主调对象定义了相应的特性。

            GetCustomAttributesData():返回有关自定义特性的信息(特性稍后便会提到)

            当然除了MemberInfo类定义的方法和属性外,Type类自己也添加了许多属性和方法:如下表(只列出一些常用的,太多了,自己可以转定义Type类看下) 

    三 System.Reflection.Assembly类

          通过Assembly可以动态加载程序集,并查询程序集内部信息.Assembly中有三种方法加载程序集:Load,Loadform,LoadFile.

        *如果引用了命名空间,则就直接用Load方法,参数里写上命名空间+类名就可加载。

        *若仅仅知道一个dll文件,则就要用LoadFrom方法,参数里直接填写完整的路径。LoadFrom只能用于加载不同标识的程序集,即唯一的程序集,不能加载标识相同但路径不同的程序集

        *Loadfile,加载指定路径上的程序集文件;与上述两方法不同的是:它不会加载此程序集中引用的其他的程

    序集,且不会加载相同标识的程序集。

    举例:

          Assembly assembly = Assembly.Load("MyAssembly"); //引用命名空间  
          Assembly assembly2 = Assembly.LoadFrom("D:	estDll.dll");   
          Assembly dll = Assembly.LoadFile(Environment.CurrentDirectory + "\testDll.dll");                        //通过dll文件去反射其中所有的类型,但不会加载引用的程序集</span>  

    三 使用反射

       通过使用Type类定义的方法和属性,我们能够在运行时获得类型的各种具体信息。这是一个非常强大的功能。我们一旦得到类型信息,就可以调用其构造函数,方法,和属性。可见,反射是允许使用编译时不可用的代码的。

      四种关键的反射技术:

    1.获取方法的信息

    2.调用方法

    3.构造对象

    4.从程序集中加载类型

    四 获取成员的信息

    public class RefClass : Object
        {
            private int _test3;
            private int _test1 { get; set; }
            protected int Test2 { get; set; }
            public int Test3 { get; set; }
    
            private static void Show2()
            {
            }
    
            public static void Show3()
            {
            }
    
            public void Show()
            {
    
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Type t = typeof(RefClass);
                Func<MemberTypes, string> getType = (x) =>
                    {
                        switch (x)
                        {
                            case MemberTypes.Field:
                                {
                                    return "字段";
                                }
    
                            case MemberTypes.Method:
                                {
                                    return "方法";
                                }
                            case MemberTypes.Property:
                                {
                                    return "属性";
                                }
                            default:
                                {
                                    return "未知";
                                }
                        }
                    };
    
    
                MemberInfo[] mis = t.GetMembers(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static);
    
                foreach (MemberInfo mi in mis)
                {
                    Console.WriteLine("类型成员的名称{0},类型:{1}", mi.Name,getType(mi.MemberType));
                }
                Console.ReadLine();
            }
        }

    五  获取字段的信息

    public class RefClass 
        {
            private int _test3;
            public int Test3 { get; set; }
    
    
            private int _test1 { get; set; }
            protected int Test2 { get; set; }
    
            
    
            private static void Show2()
            {
            }
    
            public static void Show3()
            {
            }
    
            public void Show()
            {
    
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Type t = typeof(RefClass);
    
                RefClass rc = new RefClass();
                rc.Test3 = 3;
    
                FieldInfo[] fis = t.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static);
    
                foreach (FieldInfo  fi in fis)
                {
                    fi.SetValue(rc,100);
                    Console.WriteLine("字段成员的名称{0},字段类型:{1},rc中的值{2}", fi.Name,fi.FieldType,fi.GetValue(rc));
                }
                Console.ReadLine();
            }
    }                             

    六 获取属性的信息

    public class RefClass
        {
            private int _test3;
            public int Test3 { get; set; }
    
    
            private int _test1 { get; set; }
            protected int Test2 { get; set; }
    
    
    
            private static void Show2()
            {
            }
    
            public static void Show3()
            {
            }
    
            public void Show()
            {
    
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Type t = typeof(RefClass);
    
                RefClass rc = new RefClass();
                PropertyInfo[] fis = t.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static);
                foreach (PropertyInfo fi in fis)
                {
                    MethodInfo getinfo = fi.GetGetMethod(true);
                     Console.WriteLine("get方法的名称{0}  返回值类型:{1}  参数数量:{2}  MSIL代码长度:{3} 局部变量数量:{4}", 
                         getinfo.Name, 
                         getinfo.ReturnType.ToString(),
                         getinfo.GetParameters().Count(),
                         getinfo.GetMethodBody().GetILAsByteArray().Length, 
                         getinfo.GetMethodBody().LocalVariables.Count);
    
                     MethodInfo setinfo = fi.GetSetMethod(true);
                     Console.WriteLine("set方法的名称{0}  返回值类型:{1}  参数数量:{2}  MSIL代码长度:{3} 局部变量数量:{4}", 
                         setinfo.Name, 
                         setinfo.ReturnType.ToString(),
                         setinfo.GetParameters().Count(),
                         setinfo.GetMethodBody().GetILAsByteArray().Length,
                         setinfo.GetMethodBody().LocalVariables.Count);
     
                     setinfo.Invoke(rc, new object[] { 123 }); //设置值
    
                     object obj = getinfo.Invoke(rc, null);
                     Console.WriteLine("方法名:{0}  内部值:{1}", fi.Name, obj);//读出值
                }
                Console.ReadLine();
            }
        }

    七 获取方法的信息

    BindingFlags是一个枚举,枚举值有(很多只列出5个吧):

    1. DeclareOnly:仅获取指定类定义的方法,而不获取所继承的方法;
    2. Instance:获取实例方法
    3. NonPublic: 获取非公有方法
    4. Public: 获取共有方法
    5. Static:获取静态方法
    public class RefClass
        {
            private int _test3;
            private int _test1 { get; set; }
            protected int Test2 { get; set; }
            public int Test3 { get; set; }
    
            private static void Show2()
            {
    
            }
    
            public static string Show3(string s)
            {
                int b;
                int c;
                return s;
            }
            public string Show(string s)
            {
                string a; 
    return s; } } class Program { static void Main(string[] args) { RefClass rc = new RefClass(); Type t = typeof(RefClass); MethodInfo[] mis = t.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Static); foreach (MethodInfo mi in mis) { if ((mi.GetParameters().Count() > 0) && (mi.GetParameters()[0].ParameterType == typeof(string))) { var a = new[] { "123" }; object obj = mi.Invoke(rc, a); MethodBody mbody = mi.GetMethodBody(); Console.WriteLine("拥有参数的方法名:{0} 返回值类型:{1} 参数1类型:{2} 参数1名称:{3} 方法调用后返回的值:{4}", mi.Name, mi.ReturnType.ToString(), mi.GetParameters()[0].ParameterType.ToString(), mi.GetParameters()[0].Name, obj.ToString()); } else { MethodBody mbody = mi.GetMethodBody(); Console.WriteLine("没有参数的方法名:{0} 返回值类型:{1}", mi.Name, mi.ReturnType.ToString()); } } Console.ReadKey(); } }

    八 动态创建对象

    class MyClass
        {
            int x;
            int y;
            public MyClass(int i)
            {
                x = y + i;
            }
            public MyClass(int i, int j)
            {
                x = i;
                y = j;
            }
            public int sum()
            {
                return x + y;
            }
        }
        class Program
        {
            static void Main()
            {
               Type t=typeof(MyClass);
    
               int val;
               ConstructorInfo[] ci = t.GetConstructors(); //获取构造函数的列表
    
               int x;//记录构造函数的个数
               for (x = 0; x < ci.Length; x++)
               {
                   ParameterInfo[] pi = ci[x].GetParameters();
                   if (pi.Length == 2)
                       break;
               }
               if (x == ci.Length)
               {
                   return;
               }
    
    
               object[] consargs = new object[2];
               consargs[0] = 10;
               consargs[1] = 20;
               object reflectOb = ci[x].Invoke(consargs);//实例化一个这个构造函数有两个参数的类型对象,如果参数为空,则为null
    
               //实例化后,调用MyClass中的方法
               MethodInfo[] mi = t.GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
               foreach (MethodInfo m in mi)
               {
                   if (m.Name.Equals("sum", StringComparison.Ordinal))
                   {
                       val = (int)m.Invoke(reflectOb, null);  //由于实例化类型对象的时候是用的两个参数的构造函数,所以这里返回的结构为30
                       Console.WriteLine(" sum is " + val);  //输出 sum is 30
                   }
               }
               Console.ReadKey();
            }
        }
  • 相关阅读:
    【分布式架构】“spring cloud”与“dubbo”微服务的对比
    gradle项目与maven项目互转
    Maven和Gradle对比
    从头开始搭建一个dubbo+zookeeper平台
    Kafka、 RabbitMQ、Redis、 ZeroMQ、 ActiveMQ、 Kafka/Jafka 对比
    Docker下redis的主从、持久化配置
    HIBERNATE与 MYBATIS的对比
    叶金荣:MySQL通用优化技巧
    为 Virtual Box 中的 CentOS 6.6 配置本地DVD光盘做yum软件源
    eclipse发布项目时,会自动还原server.xml和content.xml文件
  • 原文地址:https://www.cnblogs.com/wyh19941210/p/7398057.html
Copyright © 2011-2022 走看看