当前位置 博文首页 > God_Y:C#基础知识学习之 ?? | 反射(Reflection) 的含义和用法

    God_Y:C#基础知识学习之 ?? | 反射(Reflection) 的含义和用法

    作者:[db:作者] 时间:2021-07-04 21:59

    C# 反射(Reflection)

    反射是.NET中的重要机制,通过反射可以得到*.exe或*.dll等程序集内部的接口、类、方法、字段、属性、特性等信息,还可以动态创建出类型实例并执行其中的方法。
    反射指程序可以访问、检测和修改它本身状态或行为的一种能力。
    程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。
    可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。

    通过反射获取类型

    描述:有三种类型
    1.通过typeof获取某个值的类型

    System.Type personType=typeof(Person);
    System.Type heroType=typeof(Framework.Hero);
    

    2.通过一个对象获取该对象所对应的类的类型

    Framework.hero dmxy =new Framework.hero();
    System Type=dmxy.GetType();
    

    3.通过类的名称字符串获取对应的类型

    System.Type strType =System.Type.GetType("Person");
    System.Type strType =System.Type.GetType("Framework.Hero");
    

    Type类

    属性

    • Name 数据类型名
    • FullName 数据类型的完全限定名
    • Namespace 定义数据类型的命名空间名
    • IsAbstract 指示该类型是否是抽象类型
    • IsArray 指示该类型是否为数组
    • IsClass 指示该类型是否为类
    • IsEnum 指示该类型是否为枚举
    • IsInterface 指示该类型是否为接口
    • IsPublic 指示该类型是否为共有的
    • IsSealed 指示该类型是否是密封类
    • IsValueType 指示该类型是否为值类型
    • BaseType 父类类型
    • AssemblyQualifiedName
      程序集+命名空间+类名 | 是Type.GetType(str)中的字符串
      在这里插入图片描述
        /// <summary>
        /// 看看type里面有哪些字段
        /// </summary>
        private void ShowTypeField()
        {
            //获取类型
            Type heroType = typeof(Framework.Hero);
            //查看类型的名字
            Console.WriteLine("Name:" + heroType.Name);
            //查看类型的全名
            Console.WriteLine("FullName:" + heroType.FullName);
            //查看程序集名称
            Console.WriteLine("Assembly:" + heroType.Assembly);
            //加上程序集的全名
            Console.WriteLine("Ass-Name:" +heroType.AssemblyQualifiedName);
            //获取该类型的父类
            Console.WriteLine("BaseType:" + heroType.BaseType.BaseType);
    
            Type equipTypeType = typeof(EquipType);
        }
    

    方法

    • GetMember(),GetMembers()
      1.返回MemberInfo类型,用于取得该类的所有成员的信息
      2.GetConstructor(),GetConstructors() -返回ConstructorInfo类型,用于取得该类构造函数的信息
    • GetEvent(),GetEvents()
      返回EventInfo类型,用于取得该类的事件的信息
    • GetInterface(),GetInterfaces()
      返回InterfaceInfo类型,用于取得该类实现的接口的信息
    • GetField(),GetFields()
      返回FieldInfo类型,用于取得该类的字段(成员变量)的信息
    • GetPropeerty(),GetProperties()
      返回ProperyInfo类型,用于取得该类的属性的信息
    • GetMethod(),GetMethods()
      返回MethodInfo类型,用于取得该类的方法的信息

    在这里插入图片描述


    反射(Reflection)的用途

    反射(Reflection)有下列用途:

    • 它允许在运行时查看特性(attribute)信息。
    • 它允许审查集合中的各种类型,以及实例化这些类型。
    • 它允许延迟绑定的方法和属性(property)。
    • 它允许在运行时创建新类型,然后使用这些类型执行一些任务。
    类型作用
    Assembly定义和加载程序集,加载程序集清单中列出的模块,以及从此程序集中查找类型并创建该类型的实例
    Module了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法
    ConstructorInfo了解构造器的名称、参数、访问修饰符(如public或private)和实现详细信息(如abstract或virtual)等。使用Type的GetConstructors或GetConstructor方法来调用特定的构造函数
    MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如public或private)和实现详细信息(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法来调用特定的方法
    FieldInfo了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值
    EventInfo了解事件的名称、事件处理程序数据类型、自定义特性、声明类型和反射类型等,并添加或移除事件处理程序
    PropertyInfo了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,并获取或设置属性值
    ParameterInfo了解参数的名称、数据类型、参数是输入参数还是输出参数等,以及参数在方法签名中的位置等

    BindingFlags

    BindingFlags的作用是 按照权限来获取类型的

     MemberInfo[] memberInfo_12 = type.GetMembers(BindingFlags.NonPublic | BindingFlags.Public);
      MemberInfo[] memberInfo_13 = type.GetMembers(BindingFlags.NonPublic | BindingFlags.Instance);
      MemberInfo[] memberInfo_23 = type.GetMembers(BindingFlags.Public | BindingFlags.Instance);
    
    组合意义
    BindingFlag.Public BindingFlags.Instance指定 public 修饰的实例成员
    BindingFlag.Public -BindingFlags.Static指定 public 修饰的静态成员
    BindingFlag.NonPublic -BindingFlags.Instance指定 private/protect/internal 修饰的实例成员
    BindingFlag.NonPublic - BindingFlags.Static指定 private/protect/internal 修饰的静态成员
    BindingFlag.Public -BindingFlags.Static -BindingFlags.Instance指定 public 修饰的静态成员和实例成员
    BindingFlag.NonPublic - BindingFlags.Static - BindingFlags.Instance指定 private/protect/internal 修饰的静态成员和实例成员

    在这里插入图片描述

    Activator

    Activator的作用是 通过反射几种不同的构造来实例化对象

    在这里插入图片描述

      /// <summary>
        /// 通过反射实例化对象
        /// </summary>
        private void NewObjByRef()
        {
            //获取类型
            Type heroType = typeof(Framework.Hero);
    
            //创建该类的实例,通过public无参构造
            // object heroObj = Activator.CreateInstance(heroType);
            // //转换成指定类型的对象
            // Framework.Hero hero = heroObj as Framework.Hero;
    
            //创建该类的实例,通过非公有无参构造
            Activator.CreateInstance(heroType, true);
    
            //创建该类的实例,通过公有有参构造
            object daysHero = Activator.CreateInstance(heroType, 31);
    
            Debug.Log((daysHero as Framework.Hero).GetName()); 
    
            //创建该类的实例,通过私有有参构造
            object privateHero = Activator.CreateInstance(heroType,
                BindingFlags.NonPublic | BindingFlags.Instance,
                null,new object[] { "QF" },
                null );
            
            Debug.Log((privateHero as Framework.Hero).attack);
        }
    

    MemberInfo

    MemberInfo的作用是 通过反射获取某个类的各种成员

    在这里插入图片描述

    //获取类型
            Type heroType = typeof(Framework.Hero);
            //获取一个类的某个成员
            // MemberInfo[] infos = heroType.GetMember("name");
            //打印结果
            // Debug.Log(infos[0].MemberType);
    
            Type goType = typeof(GameObject);
            
            //获取一个类的所有非公有静态成员
            MemberInfo[] memberInfos = goType.GetMembers(BindingFlags.NonPublic | BindingFlags.Static);
    
            for (int i = 0; i < memberInfos.Length; i++)
            {
                Debug.Log(memberInfos[i].Name + "|" + memberInfos[i].MemberType);
            }
    

    FieldInfo

    FieldInfo的作用是 通过反射获取某个对象的私有成员字段

    在这里插入图片描述

         #region 通过反射获取某个对象的私有成员字段
            //声明一个该类的对象
            Framework.Hero akl = new Framework.Hero("阿卡丽",123);
            //获取该类型的字段信息【name】
            FieldInfo fieldInfo = heroType.GetField("name",BindingFlags.NonPublic | BindingFlags.Instance);
            //获取该对象,该字段的值
            string aklName = fieldInfo.GetValue(akl).ToString();
            //设置该对象,该字段的值
            fieldInfo.SetValue(akl,"离群之刺");
            Debug.Log("aklName:" + akl.GetName());
            #endregion
    
    

    MethodInfo

    MethodInfo的作用是 通过反射获取某个类的私有方法

    在这里插入图片描述

        #region 通过反射获取某个类的私有方法
    
            Framework.Hero ftml = new Framework.Hero("发条魔灵",80);
            
            //获取非静态成员方法ShowMe
            MethodInfo info = heroType.GetMethod("ShowMe",
                BindingFlags.NonPublic |
                BindingFlags.Instance,null,CallingConventions.Any,new Type[] {typeof(string)}, null);
    
            // MethodInfo info = heroType.GetMethod("ShowMe",
            //     BindingFlags.NonPublic |
            //     BindingFlags.Instance,null,CallingConventions.Any,types, null);
    
            //调用该方法
            info.Invoke(ftml, new object[]{ "QF" });
    
            #endregion
    

    优缺点

    优 点 \color{FF66FF}{优点}
    1 、 反 射 提 高 了 程 序 的 灵 活 性 和 扩 展 性 。 \color{FF66FF}{1、反射提高了程序的灵活性和扩展性。} 1
    2 、 降 低 耦 合 性 , 提 高 自 适 应 能 力 。 \color{FF66FF}{2、降低耦合性,提高自适应能力。} 2