一、反射简介

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命名空间包含的主要类
序号 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();
peopleInfo.Age = 23;
System.Type type1 = peopleInfo.GetType();
System.Type type2 = peopleInfo.Age.GetType();

3

//通过GetType获取类名称类型

System.Type type = System.Type.GetType("Test_Reflection.PeopleInfo");

注意:PeopleInfo为自建类


  1. /***
  2. * Title:"测试反射" 项目
  3. * 主题:人员信息
  4. * Description:
  5. * 功能:XXX
  6. * Date:2022
  7. * Version:0.1版本
  8. * Author:Coffee
  9. * Modify Recoder:
  10. */
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Text;
  14. namespace Test_Reflection
  15. {
  16. class PeopleInfo
  17. {
  18. private string guid=Guid.NewGuid().ToString();
  19. public string desc= "人员信息";
  20. public string Id { get; set; }
  21. public string Name { get; set; }
  22. public string Sex { get; set; }
  23. public int Age { get; set; }
  24. public string Work { get; set; }
  25. private string WorkFlow(string opc)
  26. {
  27. //1、规划当天内容
  28. //2、设置当天内容的紧急程度
  29. //3、根据紧急情况进行处理
  30. //4、总结一天内容
  31. return $"工作流处理完成:{opc}";
  32. }
  33. public static string Test()
  34. {
  35. Console.WriteLine("这是一个测试");
  36. return "这是一个静态的方法执行完成";
  37. }
  38. public PeopleInfo()
  39. {
  40. }
  41. public PeopleInfo(string name,int age)
  42. {
  43. this.Name = name;
  44. this.Age = age;
  45. }
  46. }//Class_end
  47. }

2.3、Type类内容

2.3.1、Type类的属性

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 对象类型的【程序集.命名空间.类名】字符串

使用示例:


  1. //通过Typeof获取某个值的类型
  2. private void btn_GetType1_Click(object sender, EventArgs e)
  3. {
  4. System.Type type = typeof(PeopleInfo);
  5. string str = string.Empty;
  6. str += $"1-对象类型名称:{type.Name}";
  7. str += $"2-对象类型的全名:{type.FullName}";
  8. str += $"3-对象类型的命名空间:{type.Namespace}";
  9. str += $"4-对象类型是否为抽象类型:{type.IsAbstract}";
  10. str += $"5-对象类型是否为数组:{type.IsArray}";
  11. str += $"6-对象类型是否为类:{type.IsClass}";
  12. str += $"7-对象类型是否为枚举:{type.IsEnum}";
  13. str += $"8-对象类型是否为接口:{type.IsInterface}";
  14. str += $"9-对象类型是否为公有:{type.IsPublic}";
  15. str += $"10-对象类型是否为密封类:{type.IsSealed}";
  16. str += $"11-对象类型是否为值类型:{type.IsValueType}";
  17. str += $"12-对象类型的基类类型:{type.BaseType}";
  18. str += $"13-对象类型的【程序集】字符串:{type.Assembly}";
  19. str += $"14-对象类型是否是COM对象:{type.IsCOMObject}";
  20. str += $"15-对象类型的【程序集.命名空间.类名】字符串:{type.AssemblyQualifiedName }";
  21. }

执行效果如下:

2.3.2、Type类的方法

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类型说明
序号 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反射不同的构造进行实例化对象
序号 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反射不同的构造进行实例化对象示例代码


  1. System.Type type = System.Type.GetType("Test_Reflection.PeopleInfo");
  2. //通过无参构造创建实例
  3. object obj = Activator.CreateInstance(type);
  4. //将对象转为PeopleInfo类
  5. PeopleInfo peopleInfo1 = obj as PeopleInfo;
  6. str += $"描述1:{peopleInfo1.desc} 名称1:{peopleInfo1.Name} 年龄1:{peopleInfo1.Age}{enterEffect}";
  7. System.Type type111 = typeof(PeopleInfo);
  8. //通过有参构造创建实例
  9. dynamic obj2 = Activator.CreateInstance(type111, System.Reflection.BindingFlags.Instance|
  10. System.Reflection.BindingFlags.Public,null,new object[] {"卓一航",26},null);
  11. str += $"描述2:{obj2.desc} 名称2:{obj2.Name} 年龄2:{obj2.Age}{enterEffect}";

Activator反射不同的构造进行实例化对象示例代码效果

2.6、FieldInfo 通过反射获取对象的成员字段

FieldInfo 通过反射获取对象的成员字段
序号 FieldInfo字段名称 说明
1 GetField(字段名称,访问权限System.Reflection.BindingFlags组合) 返回指定权限和名称的字段
2 GetFields(访问权限System.Reflection.BindingFlags组合) 返回指定权限的所有字段
3 SetValue(对象,值) 设置对象下该字段的值
4 GetValue(对象) 获取对象下该字段的值

FieldInfo 通过反射获取对象的成员字段示例:


  1. PeopleInfo peopleInfo = new PeopleInfo();
  2. peopleInfo.Id = "CK00988";
  3. peopleInfo.Name = "张一山";
  4. peopleInfo.Sex = "男";
  5. peopleInfo.Age = 23;
  6. peopleInfo.Work = "信息部总监";
  7. System.Reflection.FieldInfo fi2 = type1.GetField("desc",System.Reflection.BindingFlags.Instance|System.Reflection.BindingFlags.Public);
  8. str += $"修改前字段的值:{fi2.GetValue(peopleInfo)} {enterEffect}";
  9. fi2.SetValue(peopleInfo,"修改后的值");
  10. str += $"修改后字段的值:{fi2.GetValue(peopleInfo)} {enterEffect}";
  11. System.Reflection.FieldInfo[] fi = type1.GetFields(System.Reflection.BindingFlags.Instance |
  12. System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
  13. if (fi != null)
  14. {
  15. foreach (var item in fi)
  16. {
  17. str += $"字段名称:{item.Name} 类型:{item.FieldType} 声明此成员的类为:{item.DeclaringType} 模块:{item.Module} 值:{item.GetValue(peopleInfo)} {enterEffect}";
  18. }
  19. }

FieldInfo 通过反射获取对象的成员字段运行效果:

2.7、MethodInfo 通过反射获取某个类的方法

MethodInfo 通过反射获取某个类的方法
序号 MethodInfo方法名称 说明
1 Name 获取方法名称
2 MemberType 获取方法类型
3 InvokeMember 回调方法
4 GetMethod 获取方法且返回【MethodInfo】

MethodInfo 通过反射获取某个类的方法且执行示例:


  1. System.Type type = System.Type.GetType("Test_Reflection.PeopleInfo");
  2. //通过无参构造创建实例
  3. object obj = Activator.CreateInstance(type);
  4. System.Reflection.MethodInfo[] mi = type1.GetMethods(System.Reflection.BindingFlags.Instance| System.Reflection.BindingFlags.NonPublic
  5. );
  6. if (mi != null)
  7. {
  8. foreach (var item in mi)
  9. {
  10. str += $"方法名称:{item.Name} 类型:{item.MemberType} 声明此成员的类为:{item.DeclaringType} 模块:{item.Module} {enterEffect}";
  11. }
  12. }
  13. //反射调用方法一
  14. string result = (string)type.InvokeMember("WorkFlow", System.Reflection.BindingFlags.InvokeMethod |
  15. System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance,
  16. null, obj, new object[] { "测试传入的参数11111" });
  17. str += $"反射调用方法一:{result} {enterEffect}";
  18. //反射调用方法二
  19. System.Reflection.MethodInfo mi222 =type.GetMethod("WorkFlow",
  20. System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
  21. | BindingFlags.IgnoreCase);
  22. string result2 = (string)mi222.Invoke(obj,new object[] {"测试传入的参数22222" });
  23. str += $"反射调用方法二:{result2} {enterEffect}";
  24. //反射调用方法三
  25. System.Reflection.MethodInfo mi333 = type.GetMethod("Test");
  26. string result3 = (string)mi333.Invoke(null,null);
  27. str += $"反射调用静态方法:{result3} {enterEffect}";

MethodInfo 通过反射获取某个类的方法且执行效果:

2.8、PropertyInfo、EventInfo 和MemberInfo、ConstructorInfo


  1. PeopleInfo peopleInfo = new PeopleInfo();
  2. peopleInfo.Id = "CK00988";
  3. peopleInfo.Name = "张一山";
  4. peopleInfo.Sex = "男";
  5. peopleInfo.Age = 23;
  6. peopleInfo.Work = "信息部总监";
  7. System.Type type1 = peopleInfo.GetType();
  8. System.Reflection.PropertyInfo[] pi = type1.GetProperties();
  9. if (pi != null)
  10. {
  11. foreach (var item in pi)
  12. {
  13. str += $"属性名称:{item.Name} 类型:{item.MemberType} 声明此成员的类为:{item.DeclaringType} 模块:{item.Module} {enterEffect}";
  14. }
  15. }
  16. System.Reflection.EventInfo[] eventInfo = type1.GetEvents();
  17. if (eventInfo!=null)
  18. {
  19. foreach (var item in eventInfo)
  20. {
  21. str += $"事件名称:{item.Name} 类型:{item.EventHandlerType} 声明此成员的类为:{item.DeclaringType} 模块:{item.Module} {enterEffect}";
  22. }
  23. }
  24. System.Reflection.MemberInfo[] type3 = type1.GetMember("Name");
  25. if (type3 != null)
  26. {
  27. foreach (var item in type3)
  28. {
  29. str += $"成员名称:{item.Name} 类型:{item.MemberType} 声明此成员的类为:{item.DeclaringType} {enterEffect}";
  30. }
  31. }
  32. System.Reflection.MemberInfo[] type4 = type1.GetMembers();
  33. if (type4 != null)
  34. {
  35. foreach (var item in type4)
  36. {
  37. str += $"成员名称:{item.Name} 类型:{item.MemberType} 声明此成员的类为:{item.DeclaringType} {enterEffect}";
  38. }
  39. }
  40. System.Reflection.ConstructorInfo[] ci = type1.GetConstructors();
  41. if (ci != null)
  42. {
  43. foreach (var item in ci)
  44. {
  45. str += $"构造成员名称:{item.Name} 类型:{item.MemberType} 声明此成员的类为:{item.DeclaringType} 模块:{item.Module} {enterEffect}";
  46. System.Reflection.ParameterInfo[] pi111 = item.GetParameters();
  47. if (pi111 != null)
  48. {
  49. for (int i = 0; i < pi111.Length; i++)
  50. {
  51. str += $"参数{i}是:{pi111[i]} {enterEffect}";
  52. }
  53. }
  54. }
  55. str += enterEffect;
  56. }
  57. //通过无参构造创建实例
  58. object obj = Activator.CreateInstance(type);
  59. //将对象转为PeopleInfo类
  60. PeopleInfo peopleInfo1 = obj as PeopleInfo;
  61. 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 Docshttps://docs.microsoft.com/zh-cn/dotnet/framework/reflection-and-codedom/viewing-type-information

转自 https://blog.csdn.net/xiaochenXIHUA/article/details/123005133

[转]C#的反射的更多相关文章

  1. 隐私泄露杀手锏 —— Flash 权限反射

    [简版:http://weibo.com/p/1001603881940380956046] 前言 一直以为该风险早已被重视,但最近无意中发现,仍有不少网站存在该缺陷,其中不乏一些常用的邮箱.社交网站 ...

  2. Java学习之反射机制及应用场景

    前言: 最近公司正在进行业务组件化进程,其中的路由实现用到了Java的反射机制,既然用到了就想着好好学习总结一下,其实无论是之前的EventBus 2.x版本还是Retrofit.早期的View注解框 ...

  3. 关于 CSS 反射倒影的研究思考

    原文地址:https://css-tricks.com/state-css-reflections 译者:nzbin 友情提示:由于演示 demo 的兼容性,推荐火狐浏览.该文章篇幅较长,内容庞杂,有 ...

  4. 编写高质量代码:改善Java程序的151个建议(第7章:泛型和反射___建议106~109)

    建议106:动态代理可以使代理模式更加灵活 Java的反射框架提供了动态代理(Dynamic Proxy)机制,允许在运行期对目标类生成代理,避免重复开发.我们知道一个静态代理是通过主题角色(Prox ...

  5. 运用Mono.Cecil 反射读取.NET程序集元数据

    CLR自带的反射机智和API可以很轻松的读取.NET程序集信息,但是不能对程序集进行修改.CLR提供的是只读的API,但是开源项目Mono.Cecil不仅仅可以读取.NET程序集的元数据,还可以进行修 ...

  6. .NET面试题系列[6] - 反射

    反射 - 定义,实例与优化 在面试中,通常会考察反射的定义(操作元数据),可以用反射做什么(获得程序集及其各个部件),反射有什么使用场景(ORM,序列化,反序列化,值类型比较等).如果答得好,还可能会 ...

  7. .NET基础拾遗(4)委托、事件、反射与特性

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

  8. C++的性能C#的产能?! - .Net Native 系列五:.Net Native与反射

    此系列系小九的学堂原创翻译,翻译自微软官方开发向导,一共分为六个主题.本文是第五个主题:.Net Native与反射. 向导文链接:<C++的性能C#的产能?! - .Net Native 系列 ...

  9. [源码]Literacy 快速反射读写对象属性,字段

    Literacy 说明 Literacy使用IL指令生成方法委托,性能方面,在调用次数达到一定量的时候比反射高很多 当然,用IL指令生成一个方法也是有时间消耗的,所以在只使用一次或少数几次的情况,不但 ...

  10. SI与EMI(一) - 反射是怎样影响EMI

    Mark为期两天的EMC培训中大概分成四个时间差不多的部分,简单来说分别是SI.PI.回流.屏蔽.而在信号完整性的书籍中,也会把信号完整性分为:1.信号自身传输的问题(反射,损耗):2.信号与信号之间 ...

随机推荐

  1. DELLR740服务器安装centos7.9操作系统时发现无法检测到硬盘

    问题:RAID卡:PERC H750 安装centos7.9操作系统时发现无法检测到硬盘 解决办法: 1.需要先配置RAID2.如果不配RAID的话,需要在F2选项中的RAID配置中开启NON-RAI ...

  2. 记一次 .NET 某医保平台 CPU 爆高分析

    一:背景 1. 讲故事 一直在追这个系列的朋友应该能感受到,我给这个行业中无数的陌生人分析过各种dump,终于在上周有位老同学找到我,还是个大妹子,必须有求必应 . 妹子公司的系统最近在某次升级之后, ...

  3. JZOJ 5352. 【NOIP2017提高A组模拟9.7】计数题

    题目 分析 考虑 \(kruskal\) 的过程 我们选边从高位开始 当前位为 \(0\) 的放一边,为 \(1\) 的放另一边 将 \(0\) 的建一棵字典树, \(1\) 的匹配 因为是异或,那就 ...

  4. 安卓ro.serialno产生的整个流程

    前言: 关于ro.serialno这个属性,相信大家都不陌生了,应用层的Build.getSerial(),Build.SERIAL等均是直接或间接的获取了这个属性值.接下来从boot到系统应用,小小 ...

  5. PostgreSQL控制文件讲解及案例

    PostgreSQL控制文件内容: 主要分为是三部分,初始化静态信息.WAL及检查点的动态信息.一些配置信息. 我们可以用过pg_controldata命令直接读取PostgreSQL控制文件内容: ...

  6. Python实战项目5-Git远程仓库/分支合并/冲突解决

    Git分支 为什么要有分支 可以保证主分支的版本都是可以查看的版本 我们都在开发分支开发,开发完成 合并代码 分支操作 分支查看 git branch 分支创建 git branch 分支名 分支切换 ...

  7. 自定义顺序表ArrayList

    1.简介 顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素.使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通 ...

  8. LeetCode-475 供暖器

    来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/heaters 题目描述 冬季已经来临. 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖. ...

  9. getUserInfo和getUserProfile被废弃

    之前得知获取用户头像和昵称的两个接口getUserInfo和getUserProfile被废弃了,于是我就想深入探究一下. 一直抱有一个疑问,为啥有getUserInfo和getUserProfile ...

  10. Windows 干净启动

    1. 卸载设备中全部的第三方反病毒软件与系统优化软件 (例如 360.腾讯电脑管家.鲁大师等).2. 按 "Windows 徽标键+R",输入 "msconfig&quo ...