反射

反射是.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)中的字符串

    属性作用
    Name数据类型名
    FullName数据类型的完全限定名(包括命名空间名)
    Namespace定义数据类型的命名空间名
    isAbstract指示该类型是否是抽象类
    isArray指示该类型是否是数组
    isClass指示该类型是否是类
    isEnum指示该类型是否是类
    isInterface指示该类型是否是接口
    isPublic指示该类型是否是公有的
    isSealed指示该类型是否是密封类
    isValueType指示该类型是否是值类型
    AssemblyQualifiedName程序集+命名空间+类名, 是Type.GetType(str)中的字符串
    BaseType父类类型
/// <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.GetMember(BindingFlags.NonPublic | BindingFlagsPublic); 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(FrameworkHero); //创建该类的实例,通过public无参构造 // object heroObj = ActivatorCreateInstance(heroType); // //转换成指定类型的对象 // Framework.Hero hero = heroObj asFramework.Hero; //创建该类的实例,通过非公有无参构造 Activator.CreateInstance(heroType,true); //创建该类的实例,通过公有有参构造 object daysHero = ActivatorCreateInstance(heroType, 31); Debug.Log((daysHero as FrameworkHero).GetName()); //创建该类的实例,通过私有有参构造 object privateHero = ActivatorCreateInstance(heroType, BindingFlags.NonPublic |BindingFlags.Instance, null,new object[] { "QF" }, null ); Debug.Log((privateHero as FrameworkHero).attack); }

MemberInfo

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

//获取类型 Type heroType = typeof(FrameworkHero); //获取一个类的某个成员 // MemberInfo[] infos = heroTypeGetMember("name"); //打印结果 // Debug.Log(infos[0].MemberType); Type goType = typeof(GameObject); //获取一个类的所有非公有静态成员 MemberInfo[] memberInfos = goTypeGetMembers(BindingFlags.NonPublic |BindingFlags.Static); for (int i = 0; i < memberInfosLength; 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

优缺点

优点:

  1. 反射提高了程序的灵活性和扩展性。
  2. 降低耦合性,提高自适应能力
  3. 它允许程序创建和控制任何类的对象,无需提前硬编码目标类。

缺点:

  1. 性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。
  2. 使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。

反射的作用很大,这里只是介绍了反射的定义和一些使用方法 想要做一些更复杂的使用还是要去项目中实践才能体会的到,这里就只简单介绍一下,当个入门门槛