
通过反射获取类型反射是.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类
属性
///方法/// 看看type里面有哪些字段 /// 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); }
反射(Reflection)有下列用途:
| 类型 | 作用 |
|---|---|
| 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的作用是 按照权限来获取类型的
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的作用是 通过反射几种不同的构造来实例化对象
///MemberInfo/// 通过反射实例化对象 /// 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的作用是 通过反射获取某个类的各种成员
//获取类型
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、降低耦合性,提高自适应能力。
3
、
它
允
许
程
序
创
建
和
控
制
任
何
类
的
对
象
,
无
需
提
前
硬
编
码
目
标
类
。
color{FF66FF}{3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。}
3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。
缺
点
color{2D4AFF}{缺点}
缺点
1
、
性
能
问
题
:
使
用
反
射
基
本
上
是
一
种
解
释
操
作
,
用
于
字
段
和
方
法
接
入
时
要
远
慢
于
直
接
代
码
。
因
此
反
射
机
制
主
要
应
用
在
对
灵
活
性
和
拓
展
性
要
求
很
高
的
系
统
框
架
上
,
普
通
程
序
不
建
议
使
用
。
color{2D4AFF}{1、性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。}
1、性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。
2
、
使
用
反
射
会
模
糊
程
序
内
部
逻
辑
;
程
序
员
希
望
在
源
代
码
中
看
到
程
序
的
逻
辑
,
反
射
却
绕
过
了
源
代
码
的
技
术
,
因
而
会
带
来
维
护
的
问
题
,
反
射
代
码
比
相
应
的
直
接
代
码
更
复
杂
。
color{2D4AFF}{2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。}
2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。
Tips
反射的作用很大,这里只是介绍了反射的定义和一些使用方法
想要做一些更复杂的使用还是要去项目中实践才能体会的到,这里就只简单介绍一下,当个入门门槛
参考
https://blog.csdn.net/xiaouncle/article/details/52983924
https://blog.csdn.net/qq_32452623/article/details/53401890