一、反射简介

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. python requests 最牛攻略

    目录 安装 Reuqests HTTP 简介 什么是 HTTP HTTP工作原理 HTTP的9种请求方法 HTTP状态码 requests 快速上手 requests 发起请求的步骤 requests ...

  2. EPICS Archiver Appliance的定制部署2

    EPICS Archiver Appliance的定制部署1 按上面的步骤Archiver可以跑起来了,试了一下,发现waveform不能archive,看服务状态: 看起来正常,怀疑在profile ...

  3. js中的Object.keys、array.map、groupBy、call、apply总结分享

    分享几个js中的函数 Object.keys() 首先这个函数是用来干嘛的呢?是用来把一个json字符串里的key全都取出来重新整成一个数组的方法,那么这个函数怎么用呢,接下来贴出我最近碰见的用法: ...

  4. Hadoop 及Spark 分布式HA运行环境搭建

    作者:京东物流 秦彪 工欲善其事必先利其器,在深入学习大数据相关技术之前,先手动从0到1搭建一个属于自己的本地Hadoop和Spark运行环境,对于继续研究大数据生态圈各类技术具有重要意义.本文旨在站 ...

  5. Angular ngx-translate 国际化实践(中文转英文)

    1.安装包 npm install @ngx-translate/core --save npm install @ngx-translate/http-loader --save 2.根模块app. ...

  6. 常用的git提交代码命令

    日常开发使用的git提交代码的方法 一.初始化本地仓库,提交代码,提交到远程git仓库 1.初始化代码仓库git init2.将当前目录下的所有文件放到暂存区git add .3.查看文件状态git ...

  7. java double/float转BigDecimal,精度问题

    double/float 转BigDecimal,会有精度问题.所以需要转String类型,然后再转BigDecimal

  8. 20230103~05code

    目录 U190849 最简分式 P5734 [深基6.例6]文字处理软件 P1104 生日 P4305 [JLOI2011]不重复数字 P8218 [深进1.例1]求区间和 P3397 地毯 P236 ...

  9. Intellij IDEA远程debug

    1.服务器开启远程调试模式,增加JVM启动参数,以支持远程调试 服务器端的tomcat/bin/catalina.sh文件,在第一行添加参数配置如下(要确保下面的端口没有被占用).CATALINA_O ...

  10. u8g2 资料汇集

    移植U8g2 https://www.cnblogs.com/frozencandles/p/16358483.html 函数接口说明: https://github.com/olikraus/u8g ...