[转]C#的反射
一、反射简介
1.1、反射的说明
反射:指程序可以访问、检测和修改它本身状态或行为的一种能力(即:审查元数据并收集关于它的类型信息的能力)。
①元数据(编译以后的最基本数据单元:指程序和程序类型本身的的信息,保存在程序的程序集中)可以理解为一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等。
序号 | 元数据包含的内容 |
1 |
程序或类库中每一个类型的描述 |
2 | 清单信息,包括与程序本身有关的数据,以及它依赖的库 |
3 | 在代码中嵌入的自定义特性,提供与特性所修饰的构造有关的额外信息 |
②反射提供了封装程序集、模块和类型的对象(反射的层次模型为:程序集包含模块,而模块包含类型,类型又包含成员【成员--->类型--->模块--->程序集】)其中类型可以是(类、结构、枚举)。
③Type类是一个抽象类,用来包含类型的特性,这个类的对象能让我们获取程序使用的类型的信息(由于他是抽象类所以获取的是派生类实例)。
④可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
1.2、反射的用途
通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。有了反射,即可对每一个类型了如指掌。另外我还可以直接创建对象,即使这个对象的类型在编译时还不知道。
《1》反射的整体用途说明
①它允许在运行时查看特性(attribute)信息。
②它允许审查集合中的各种类型,以及实例化这些类型。
③它允许延迟绑定的方法和属性(property)。
④它允许在运行时创建新类型,然后使用这些类型执行一些任务。
《2》反射的详细用法说明
序号 | 反射的用法说明 |
1 | 使用【Assembly】定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例 |
2 | 使用【Module】了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法 |
3 | 使用【ConstructorInfo】了解构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等 |
4 | 使用【MethodInfo】了解方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等 |
5 | 使用【FiedInfo】了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值 |
6 | 使用【EventInfo】了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序 |
7 | 使用【PropertyInfo】了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值 |
8 | 使用【ParameterInfo】了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等 |
二、反射主要用到的内容
关于【C#反射】文章中涉及到的内容示例项目工程https://download.csdn.net/download/xiaochenXIHUA/81895206
2.1、使用的命名空间
使用反射需要引用命名空间【using System.reflection】,这个命名空间包含如下的类:
序号 | System.Reflection命名空间包含的主要类(反射涉及到的类) |
1 | System.Reflection.Assembly |
2 | System.Reflection.MemberInfo |
3 | System.Reflection.EventInfo |
4 | System.Reflection.FieldInfo |
5 | System.Reflection.MethodBase |
6 | System.Reflection.ConstructorInfo |
7 | System.Reflection.MethodInfo |
8 | System.Reflection.PropertyInfo |
9 | System.Type |
可以使用 ILSpy 工具查看【System.reflection】命名空间包含的内容,具体的使用方法请参考:
安装使用反编译工具ILSPYhttps://coffeemilk.blog.csdn.net/article/details/120966898
2.2、获取反射类型的三种方式
序号 | 获取反射类型的三种方式 |
1 |
//通过Typeof获取某个值的类型 System.Type type = typeof(PeopleInfo); |
2 |
//通过GetType获取对象类型 PeopleInfo peopleInfo = new PeopleInfo(); |
3 |
//通过GetType获取类名称类型 System.Type type = System.Type.GetType("Test_Reflection.PeopleInfo"); |
注意:PeopleInfo为自建类
/*** * Title:"测试反射" 项目 * 主题:人员信息 * Description: * 功能:XXX * Date:2022 * Version:0.1版本 * Author:Coffee * Modify Recoder: */ using System; using System.Collections.Generic; using System.Text; namespace Test_Reflection { class PeopleInfo { private string guid=Guid.NewGuid().ToString(); public string desc= "人员信息"; public string Id { get; set; } public string Name { get; set; } public string Sex { get; set; } public int Age { get; set; } public string Work { get; set; } private string WorkFlow(string opc) { //1、规划当天内容 //2、设置当天内容的紧急程度 //3、根据紧急情况进行处理 //4、总结一天内容 return $"工作流处理完成:{opc}"; } public static string Test() { Console.WriteLine("这是一个测试"); return "这是一个静态的方法执行完成"; } public PeopleInfo() { } public PeopleInfo(string name,int age) { this.Name = name; this.Age = age; } }//Class_end }
2.3、Type类内容
2.3.1、Type类的属性
序号 | 属性名称 | 属性说明 |
1 | Name | 对象类型名称 |
2 | FullName | 对象类型的全名 |
3 | Namespace | 对象类型的命名空间 |
4 | IsAbstract | 对象类型是否为抽象类型 |
5 | IsArray | 对象类型是否为数组 |
6 | IsClass | 对象类型是否为类 |
7 | IsEnum | 对象类型是否为枚举 |
8 | IsInterface | 对象类型是否为接口 |
9 | IsPublic | 对象类型是否为公有 |
10 | IsSealed | 对象类型是否为密封类 |
11 | IsValueType | 对象类型是否为值类型 |
12 | BaseType | 对象类型的基类类型 |
13 | Assembly | 对象类型的【程序集】字符串 |
14 | IsCOMObject | 对象类型是否是COM对象 |
15 | AssemblyQualifiedName | 对象类型的【程序集.命名空间.类名】字符串 |
使用示例:
//通过Typeof获取某个值的类型 private void btn_GetType1_Click(object sender, EventArgs e) { System.Type type = typeof(PeopleInfo); string str = string.Empty; str += $"1-对象类型名称:{type.Name}"; str += $"2-对象类型的全名:{type.FullName}"; str += $"3-对象类型的命名空间:{type.Namespace}"; str += $"4-对象类型是否为抽象类型:{type.IsAbstract}"; str += $"5-对象类型是否为数组:{type.IsArray}"; str += $"6-对象类型是否为类:{type.IsClass}"; str += $"7-对象类型是否为枚举:{type.IsEnum}"; str += $"8-对象类型是否为接口:{type.IsInterface}"; str += $"9-对象类型是否为公有:{type.IsPublic}"; str += $"10-对象类型是否为密封类:{type.IsSealed}"; str += $"11-对象类型是否为值类型:{type.IsValueType}"; str += $"12-对象类型的基类类型:{type.BaseType}"; str += $"13-对象类型的【程序集】字符串:{type.Assembly}"; str += $"14-对象类型是否是COM对象:{type.IsCOMObject}"; str += $"15-对象类型的【程序集.命名空间.类名】字符串:{type.AssemblyQualifiedName }"; }
执行效果如下:
2.3.2、Type类的方法
序号 | 方法名称 | 方法说明 |
1 | GetMember("成员的名称") | 返回该成员名称对应的【MemberInfo】类型 |
2 | GetMembers() | 返回类包含的所有成员对应的【MemberInfo[]】类型 |
3 | GetConstructor() | 返回类的构造函数信息【ConstructorInfo】 |
4 | GetConstructors() | 返回类的所有构造函数信息【ConstructorInfo[]】 |
5 | GetEvent(“事件名称”) | 返回类的事件信息【EventInfo】 |
6 | GetEvents() | 返回类的所有事件信息【EventInfo[]】 |
7 | GetInterface("接口名称") | 返回类的接口信息【Type】 |
8 | GetInterfaces() | 返回类的所有接口信息【Type[]】 |
9 | GetField("字段名称") | 返回类的字段信息【FieldInfo】 |
10 | GetFields() | 返回类的所有字段信息【FieldInfo[]】 |
11 | GetPropertie("属性名称") | 返回类的属性信息【PropertyInfo】 |
12 | GetProperties() | 返回类的所有属性信息【PropertyInfo[]】 |
13 | GetMethod("方法名称") | 返回类的方法信息【MethodInfo】 |
14 | GetMethods() | 返回类的所有方法信息【MethodInfo[]】 |
2.4、BindingFlags 类型说明
序号 | BindingFlags权限类型名称(可以多项组合) | 说明 |
1 | System.Reflection.BindingFlags.Public | 指定Public修饰的成员 |
2 | System.Reflection.BindingFlags.Instance | 指定实例化的成员 |
3 | System.Reflection.BindingFlags.NonPublic | 指定Private修饰的成员 |
4 | System.Reflection.BindingFlags.Static | 指定Static修饰的成员 |
5 | System.Reflection.BindingFlags.DeclaredOnly | 指定DeclaredOnly修饰的成员 |
6 |
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance |
指定Public修饰的实例化成员 |
2.5、 Activator 反射不同的构造进行实例化对象
序号 | Activator方法 | 说明 |
1 | CreateInstance(Type t) | 使用默认Public修饰的无参数构造实例化对象 |
2 | CreateInstance(Type,bool nonPublic) | 使用Private修饰的无参构造实例化对象 |
3 | CreateInstance(Type type, params object?[]? args) | 使用Public修饰的有参构造实例化对象 |
4 | CreateInstance(Type type, object?[]? args, object?[]? activationAttributes) | 使用Public修饰的有参构造和公有属性实例化对象 |
5 | CreateInstance(Type type, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture) | 使用指定的BindingFlags组合,可选有无参数构造实例化对象 |
Activator反射不同的构造进行实例化对象示例代码
-
System.Type type = System.Type.GetType("Test_Reflection.PeopleInfo");
-
-
//通过无参构造创建实例
-
object obj = Activator.CreateInstance(type);
-
//将对象转为PeopleInfo类
-
PeopleInfo peopleInfo1 = obj as PeopleInfo;
-
-
str += $"描述1:{peopleInfo1.desc} 名称1:{peopleInfo1.Name} 年龄1:{peopleInfo1.Age}{enterEffect}";
-
-
System.Type type111 = typeof(PeopleInfo);
-
//通过有参构造创建实例
-
dynamic obj2 = Activator.CreateInstance(type111, System.Reflection.BindingFlags.Instance|
-
System.Reflection.BindingFlags.Public,null,new object[] {"卓一航",26},null);
-
-
str += $"描述2:{obj2.desc} 名称2:{obj2.Name} 年龄2:{obj2.Age}{enterEffect}";
Activator反射不同的构造进行实例化对象示例代码效果
2.6、FieldInfo 通过反射获取对象的成员字段
序号 | FieldInfo字段名称 | 说明 |
1 | GetField(字段名称,访问权限System.Reflection.BindingFlags组合) | 返回指定权限和名称的字段 |
2 | GetFields(访问权限System.Reflection.BindingFlags组合) | 返回指定权限的所有字段 |
3 | SetValue(对象,值) | 设置对象下该字段的值 |
4 | GetValue(对象) | 获取对象下该字段的值 |
FieldInfo 通过反射获取对象的成员字段示例:
PeopleInfo peopleInfo = new PeopleInfo(); peopleInfo.Id = "CK00988"; peopleInfo.Name = "张一山"; peopleInfo.Sex = "男"; peopleInfo.Age = 23; peopleInfo.Work = "信息部总监"; System.Reflection.FieldInfo fi2 = type1.GetField("desc",System.Reflection.BindingFlags.Instance|System.Reflection.BindingFlags.Public); str += $"修改前字段的值:{fi2.GetValue(peopleInfo)} {enterEffect}"; fi2.SetValue(peopleInfo,"修改后的值"); str += $"修改后字段的值:{fi2.GetValue(peopleInfo)} {enterEffect}"; System.Reflection.FieldInfo[] fi = type1.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public); if (fi != null) { foreach (var item in fi) { str += $"字段名称:{item.Name} 类型:{item.FieldType} 声明此成员的类为:{item.DeclaringType} 模块:{item.Module} 值:{item.GetValue(peopleInfo)} {enterEffect}"; } }
FieldInfo 通过反射获取对象的成员字段运行效果:
2.7、MethodInfo 通过反射获取某个类的方法
序号 | MethodInfo方法名称 | 说明 |
1 | Name | 获取方法名称 |
2 | MemberType | 获取方法类型 |
3 | InvokeMember | 回调方法 |
4 | GetMethod | 获取方法且返回【MethodInfo】 |
MethodInfo 通过反射获取某个类的方法且执行示例:
System.Type type = System.Type.GetType("Test_Reflection.PeopleInfo"); //通过无参构造创建实例 object obj = Activator.CreateInstance(type); System.Reflection.MethodInfo[] mi = type1.GetMethods(System.Reflection.BindingFlags.Instance| System.Reflection.BindingFlags.NonPublic ); if (mi != null) { foreach (var item in mi) { str += $"方法名称:{item.Name} 类型:{item.MemberType} 声明此成员的类为:{item.DeclaringType} 模块:{item.Module} {enterEffect}"; } } //反射调用方法一 string result = (string)type.InvokeMember("WorkFlow", System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, obj, new object[] { "测试传入的参数11111" }); str += $"反射调用方法一:{result} {enterEffect}"; //反射调用方法二 System.Reflection.MethodInfo mi222 =type.GetMethod("WorkFlow", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | BindingFlags.IgnoreCase); string result2 = (string)mi222.Invoke(obj,new object[] {"测试传入的参数22222" }); str += $"反射调用方法二:{result2} {enterEffect}"; //反射调用方法三 System.Reflection.MethodInfo mi333 = type.GetMethod("Test"); string result3 = (string)mi333.Invoke(null,null); str += $"反射调用静态方法:{result3} {enterEffect}";
MethodInfo 通过反射获取某个类的方法且执行效果:
2.8、PropertyInfo、EventInfo 和MemberInfo、ConstructorInfo
PeopleInfo peopleInfo = new PeopleInfo(); peopleInfo.Id = "CK00988"; peopleInfo.Name = "张一山"; peopleInfo.Sex = "男"; peopleInfo.Age = 23; peopleInfo.Work = "信息部总监"; System.Type type1 = peopleInfo.GetType(); System.Reflection.PropertyInfo[] pi = type1.GetProperties(); if (pi != null) { foreach (var item in pi) { str += $"属性名称:{item.Name} 类型:{item.MemberType} 声明此成员的类为:{item.DeclaringType} 模块:{item.Module} {enterEffect}"; } } System.Reflection.EventInfo[] eventInfo = type1.GetEvents(); if (eventInfo!=null) { foreach (var item in eventInfo) { str += $"事件名称:{item.Name} 类型:{item.EventHandlerType} 声明此成员的类为:{item.DeclaringType} 模块:{item.Module} {enterEffect}"; } } System.Reflection.MemberInfo[] type3 = type1.GetMember("Name"); if (type3 != null) { foreach (var item in type3) { str += $"成员名称:{item.Name} 类型:{item.MemberType} 声明此成员的类为:{item.DeclaringType} {enterEffect}"; } } System.Reflection.MemberInfo[] type4 = type1.GetMembers(); if (type4 != null) { foreach (var item in type4) { str += $"成员名称:{item.Name} 类型:{item.MemberType} 声明此成员的类为:{item.DeclaringType} {enterEffect}"; } } System.Reflection.ConstructorInfo[] ci = type1.GetConstructors(); if (ci != null) { foreach (var item in ci) { str += $"构造成员名称:{item.Name} 类型:{item.MemberType} 声明此成员的类为:{item.DeclaringType} 模块:{item.Module} {enterEffect}"; System.Reflection.ParameterInfo[] pi111 = item.GetParameters(); if (pi111 != null) { for (int i = 0; i < pi111.Length; i++) { str += $"参数{i}是:{pi111[i]} {enterEffect}"; } } } str += enterEffect; } //通过无参构造创建实例 object obj = Activator.CreateInstance(type); //将对象转为PeopleInfo类 PeopleInfo peopleInfo1 = obj as PeopleInfo; str += $"描述1:{peopleInfo1.desc} 名称1:{peopleInfo1.Name} 年龄1:{peopleInfo1.Age}{enterEffect}";
执行效果:
三、反射的官网参考资料
.NET 中的反射 - .NET Framework | Microsoft Docshttps://docs.microsoft.com/zh-cn/dotnet/framework/reflection-and-codedom/reflection查看类型信息 | Microsoft Docs
https://docs.microsoft.com/zh-cn/dotnet/framework/reflection-and-codedom/viewing-type-information
转自 https://blog.csdn.net/xiaochenXIHUA/article/details/123005133
[转]C#的反射的更多相关文章
- 隐私泄露杀手锏 —— Flash 权限反射
[简版:http://weibo.com/p/1001603881940380956046] 前言 一直以为该风险早已被重视,但最近无意中发现,仍有不少网站存在该缺陷,其中不乏一些常用的邮箱.社交网站 ...
- Java学习之反射机制及应用场景
前言: 最近公司正在进行业务组件化进程,其中的路由实现用到了Java的反射机制,既然用到了就想着好好学习总结一下,其实无论是之前的EventBus 2.x版本还是Retrofit.早期的View注解框 ...
- 关于 CSS 反射倒影的研究思考
原文地址:https://css-tricks.com/state-css-reflections 译者:nzbin 友情提示:由于演示 demo 的兼容性,推荐火狐浏览.该文章篇幅较长,内容庞杂,有 ...
- 编写高质量代码:改善Java程序的151个建议(第7章:泛型和反射___建议106~109)
建议106:动态代理可以使代理模式更加灵活 Java的反射框架提供了动态代理(Dynamic Proxy)机制,允许在运行期对目标类生成代理,避免重复开发.我们知道一个静态代理是通过主题角色(Prox ...
- 运用Mono.Cecil 反射读取.NET程序集元数据
CLR自带的反射机智和API可以很轻松的读取.NET程序集信息,但是不能对程序集进行修改.CLR提供的是只读的API,但是开源项目Mono.Cecil不仅仅可以读取.NET程序集的元数据,还可以进行修 ...
- .NET面试题系列[6] - 反射
反射 - 定义,实例与优化 在面试中,通常会考察反射的定义(操作元数据),可以用反射做什么(获得程序集及其各个部件),反射有什么使用场景(ORM,序列化,反序列化,值类型比较等).如果答得好,还可能会 ...
- .NET基础拾遗(4)委托、事件、反射与特性
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...
- C++的性能C#的产能?! - .Net Native 系列五:.Net Native与反射
此系列系小九的学堂原创翻译,翻译自微软官方开发向导,一共分为六个主题.本文是第五个主题:.Net Native与反射. 向导文链接:<C++的性能C#的产能?! - .Net Native 系列 ...
- [源码]Literacy 快速反射读写对象属性,字段
Literacy 说明 Literacy使用IL指令生成方法委托,性能方面,在调用次数达到一定量的时候比反射高很多 当然,用IL指令生成一个方法也是有时间消耗的,所以在只使用一次或少数几次的情况,不但 ...
- SI与EMI(一) - 反射是怎样影响EMI
Mark为期两天的EMC培训中大概分成四个时间差不多的部分,简单来说分别是SI.PI.回流.屏蔽.而在信号完整性的书籍中,也会把信号完整性分为:1.信号自身传输的问题(反射,损耗):2.信号与信号之间 ...
随机推荐
- LG P5244 [USACO19FEB] Mowing Mischief P
\(\text{Code}\) #include <bits/stdc++.h> #define IN inline #define eb emplace_back using names ...
- CentOS7一键安装RPM版LNMP(NGINX+PHP+MySQL)环境
转载:简书 CentOS7一键安装RPM版LNMP(NGINX+PHP+MySQL)环境 - 简书 (jianshu.com) (需要配置nginx.conf文件) 转载:csdn (35条消息) V ...
- 优化 Win11 资源管理器打开文件夹速度
打开"高级系统设置",点击"性能"设置,性能选项中勾选如上图选中的项,可以一定程度上提升 Win11 资源管理器打开文件夹的速度: "窗口内动画控件和 ...
- ThreadLocal及常用场景
ThreadLocal ThreadLocal是Java中的为解决多线程间数据隔离的解决方案,其底层依赖于Java的内存模型,依赖于当前执行线程的内存来完成对数据的存取操作. 一般在使用时,在对象中创 ...
- 并发JUC
JUC初级 • 1.什么是 JUC • 2.Lock 接口 • 3.线程间通信 • 4.集合的线程安全 • 5.多线程锁 • 6.Callable 接口 • 7.JUC 三大辅助类: CountDow ...
- 自我生啃 AMBA AXI 总线笔记
视频1:https://www.youtube.com/watch?v=1zw1HBsjDH8&list=PLkqJVNOiuuHtNrVaNK4O1BSgczja4obeW (What is ...
- es 6中for in与for of适用对象
在 ES6 中提供了 for-of,可以很方便的遍历数组和类数组,但是却不能遍历对象,这是为什么,与 for-in 仅仅相差一个单词,用途也是遍历,为什么却不能使用在对象上? 查资料后得知,原来 ES ...
- django-drf知识点梳理
- mysql8使用tmpfs内存磁盘当内存数据库的配置方法
序: 内存关系数据库没有找到开源好用的,很多都是商用.虽然mysql有memory引擎,但写是整体锁表,没法用. 一直想将mysql放入内存中,搜索n次资料,没找到合适的,可能之前思路不对. 最近在测 ...
- Codeforces 919E Congruence Equation(循环节+数论)
Link 题意 给$n, m, p, x$,求有多少个$n(1\leq n \leq x)$使得$n·a^{n}=b(\textrm{mod}\;p)$成立 思路 考虑一下左边的循环节长度,由于$n% ...