欢迎大家来到IT世界,在知识的湖畔探索吧!
1.反射的定义
1.1、什么是反射?
这个教程的例子都是以C#为例子的,以后有空了写个java的例子。审查元数据并收集关于它的类型信息的能力。反射来自 System.Reflection命名空间,它可以读取程序集中的元数据,利用元数据创建对象,从而实现各种功能。
1.2、什么是元数据?
(1)我们使用VS编译程序后,程序会变成程序集,主要文件为(exe文件和dll文件)
(2)程序集中包含有Microsoft 中间语言 (MSIL) 和必需的元数据。元数据存储有以下信息:
- 程序集的说明:标识(名称、版本、区域性、公钥)、导出的类型、该程序集所依赖的其他程序集、运行所需的安全权限。
- 类型的说明:名称、可见性、基类和实现的接口、成员(方法、字段、属性、事件、嵌套的类型)。
- 特性:修饰类型和成员的其他说明性元素。
1.3 反射和反编译的不同
反射读取的是元数据,反编译读取的IL代码
1.4反射的优缺点
- 优点:提高了程序的灵活性和扩展性,降低耦合度
- 缺点:由于反射多了一道程序,性能上相较于直接代码要慢
注意事项:很多时候该用反射的地方还是要用,即使牺牲一点性能
2反射相关基础概念
2.1基础模块
(1)Assembly:定义和加载程序集,加载在程序集中的所有模块以及从此程序集中查找类型并创建该类型的实例。
(2)Module:获取包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
(3)ConstructorInfo:获取构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
(4)MethodInfo(GetMethod/GetMethods):获取方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等
(5)FiedInfo(GetField/GetFields):获取字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。
(6)EventInfo(GetEvent/GetEvents):获取事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。
(7)PropertyInfo(GetProperty/GetProperties):获取属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。
(8)ParameterInfo:获取参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。
(9)MemberInfo(GetMember/GetMembers):获取字段、事件、属性等各种信息。
2.2对应C#的程序集
(1)反射的命名空间
using System.Reflection;
欢迎大家来到IT世界,在知识的湖畔探索吧!
(2)反射相关的类,简要举例子
欢迎大家来到IT世界,在知识的湖畔探索吧!System.Type System.AppDomain System.Activator System.Reflection.Assembly System.Reflection.Module System.Reflection.ConstructorInfo System.Reflection.FieldInfo System.Reflection.MethodInfo System.Reflection.PropertyInfo System.Reflection.ParameterInfo System.Reflection.MemberInfo
3、通过反射创建类的例子
(1)简单的通过反射创建类的例子
using System; using System.Reflection; public class Human { public string? Name { set; get; } public string? Id { get; set; } public Human() { } public Human(string name, string id) { this.Name = name; this.Id = id; } public void SayHello() { Console.WriteLine("Hello World!"); } public void SayHello(string m_str) { Console.WriteLine("Hello World! "+ m_str); } private void SecrectName() { Console.WriteLine("I Have a NickName haha"); } } class Demo { static void Main(string[] args) { //(一)正常的方法调用 Human human = new Human(); human.SayHello("Normal"); Console.WriteLine("-----------------"); //(二)反射的方法调用 //(1)获取当前执行代码的程序集 Assembly assembly = Assembly.GetExecutingAssembly(); Console.WriteLine(assembly.FullName); Type? type = assembly.GetType("Human");//获取类名称(要带上命名空间) if (type != null) { //(1.1)无参构造Human //创建Huamn实体,无参构造 object? o = Activator.CreateInstance(type); Human? huamn1 = o as Human; huamn1.SayHello("Reflection"); //(1.2)有参构造Human //创建Human实体,有参构造 object? o1 = Activator.CreateInstance(type, new object[] { "Li", "" }); Human? huamn2 = o1 as Human; huamn2.SayHello("Reflection2"); } } }
(2)其中
- Assembly.GetExecutingAssembly()获得了当前执行代码的程序集
- assembly.GetType(“Human”);//获取类名称(要带上命名空间)
- Activator.CreateInstance(type);//创建Huamn实体,无参构造
- Activator.CreateInstance(type, new object[] { “Li”, “” });//创建Human实体,有参构造
(3)测试结果
4、反射获取私有方法
(1)反射可以获取私有方法,简单的例子如下
欢迎大家来到IT世界,在知识的湖畔探索吧!using System; using System.Reflection; public class Human { public string? Name { set; get; } public string? Id { get; set; } private string? Money { get; set; } public Human() { } public Human(string name, string id) { this.Name = name; this.Id = id; } public void PrintHaha() { Console.WriteLine("Ha Ha!"); } public void SayHello() { Console.WriteLine("Hello World!"); } public void SayHello(string m_str) { Console.WriteLine("Hello World! " + m_str); } private void SecrectName() { Console.WriteLine("I Have a NickName haha"); } } class Demo { static void Main(string[] args) { //(一)正常的方法调用 Human human = new Human(); human.SayHello("Normal"); Console.WriteLine("-----------------"); //(二)反射的方法调用 //(1)获取当前执行代码的程序集 Assembly assembly = Assembly.GetExecutingAssembly(); Console.WriteLine(assembly.FullName); Type? type = assembly.GetType("Human");//获取类名称(要带上命名空间) if (type != null) { //(1.1)无参构造Human //创建Huamn实体,无参构造 object? o = Activator.CreateInstance(type); Human? huamn1 = o as Human; // (-1)获取公有普通方法 // 后面的BindingFlags用于限制查找方法的类型,默认不写的话只能查找到公共方法 MethodInfo? methodInfo1 = type.GetMethod("PrintHaha"); methodInfo1.Invoke(huamn1, null); // (-2)获取公有重载方法 // 后面的BindingFlags用于限制查找方法的类型,默认不写的话只能查找到公共方法 MethodInfo? methodInfo2 = type.GetMethod("SayHello", new Type[] { typeof(string) }); methodInfo2.Invoke(huamn1, new string[] { "ok" }); // 获取私有方法 // 后面的BindingFlags用于限制查找方法的类型,默认不写的话只能查找到公共方法 MethodInfo? methodInfo3 = type.GetMethod("SecrectName", BindingFlags.Instance | BindingFlags.NonPublic); methodInfo3.Invoke(huamn1, null); } } }
(2)其中
- methodInfo1 = type.GetMethod(“PrintHaha”) //获取公有普通方法
- type.GetMethod(“SayHello”, new Type[] { typeof(string) }); //获取指定重载方法
- type.GetMethod(“SecrectName”, BindingFlags.Instance | BindingFlags.NonPublic) //获取了私有方法
(3)运行结果
5、总结
(1)反射太高级了
(2)下次抽空再补充一些功能说明
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/78097.html