C# 反射详解:动态编程的利器

文章目录

  • 前言
  • 一、反射的原理
  • 二、反射的基本概念
  • 三、反射的主要API
    • 1、Type类:
    • 2、MemberInfo类:
    • 3、PropertyInfo类:
    • 4、MethodInfo类:
    • 5、Assembly类:
    • 6、EventInfo 类
    • 7、FieldInfo 类
  • 四、使用场景
  • 五、使用方法
    • 1. 获取类型信息
    • 2. 创建对象实例
    • 3. 调用方法
    • 4. 访问字段和属性
    • 5. 处理自定义特性
  • 六、实际应用示例
  • 七、反射的优缺点
  • 八、反射的注意事项
  • 总结


前言

在.NET开发中,反射(Reflection)是一个非常重要的特性,它允许在运行时对程序集中的类型、成员和方法进行查询和操作。反射提供了动态语言般的能力,可以在程序运行时动态地创建对象、调用方法、访问字段等。本文将详细介绍C#反射的原理、核心概念、API使用以及一些常见的使用场景。

一、反射的原理

在.NET框架中,C# 反射是一种强大的机制,它允许程序在运行时查询和操作类型信息。反射通过 System.Reflection 命名空间提供的类和接口实现。它使得我们可以在运行时获取程序集、模块、类型(类、接口、枚举等)的元数据,并能创建对象、调用方法、访问字段和属性等。

反射的工作原理基于.NET的元数据和公共语言运行库(CLR)。当.NET程序编译时,所有的类型信息(包括类的定义、成员、继承信息等)都会被存储在可执行文件(如DLL或EXE)中的元数据部分。反射API能够读取这些元数据,因此可以动态地获取和使用类型信息。

二、反射的基本概念

反射主要包括以下几个核心概念:
1、类型(Type): 类型是反射的基础,代表了在程序集中定义的类、接口、结构体等。类型提供了关于其成员(字段、方法、属性等)的详细信息。
2、成员(Member): 成员是类型的组成部分,包括字段、属性、方法、事件等。
3、属性(Property): 属性是类的成员,具有名称和值,通常用于封装字段。
4、方法(Method): 方法是类的成员,定义了类的操作行为,包括函数和过程。
5、参数(Parameter): 方法中的参数是传递给方法的值,用于指定方法如何执行操作。
6、Assembly(程序集): 程序集是编译后的代码库,它包含了类型和其他可重用类型定义。每个程序集都有一个唯一的标识符(Assembly Name)。

三、反射的主要API

.NET框架提供了丰富的反射API,以下是一些常用的类和方法:

1、Type类:

1.1 Type.GetType(string fullName): 获取指定完全限定名的类型。
1.2 Type.GetType(string fullName, bool throwOnError): 获取指定完全限定名的类型,如果类型不存在,则根据布尔值决定是否抛出异常。
1.3 Type.GetTypeFromProgID(string progID): 从ProgID获取类型。
1.4 Type.GetTypeFromCLSID(Guid clsid): 从CLSID获取类型。

Type type = Type.GetType("System.String");

2、MemberInfo类:

MemberInfo 类是所有成员(如字段、属性、方法等)的基类。

2.1 MemberInfo.GetHashCode():获取成员的哈希码。
2.2 MemberInfo.Equals():比较两个成员是否相等。
2.3 MemberInfo.Name: 获取成员的名称。
2.4 MemberInfo.GetCustomAttributes(Type attributeType, bool inherit) / MemberInfo.GetCustomAttributes(): 获取成员的自定义属性。

FieldInfo fieldInfo = type.GetField("myField");

3、PropertyInfo类:

PropertyInfo 类用于操作属性。

3.1 PropertyInfo.GetValue():获取属性的值。
3.2 PropertyInfo.SetValue():设置属性的值。
3.3 PropertyInfo.CanRead:检查属性是否可读。
3.4 PropertyInfo.CanWrite:检查属性是否可写。

PropertyInfo propertyInfo = type.GetProperty("MyProperty");
object value = propertyInfo.GetValue(myObject, null);

4、MethodInfo类:

MethodInfo 类用于操作方法。

4.1 MethodInfo.MethodInfo 类用于操作方法。
4.2 MethodInfo.Invoke():调用方法。
4.3 MethodInfo.GetParameters():获取方法的参数。
4.4 MethodInfo.IsStatic:检查方法是否为静态。

MethodInfo methodInfo = type.GetMethod("MyMethod");
methodInfo.Invoke(myObject, null);

5、Assembly类:

Assembly 类用于操作程序集,如获取程序集的名称、版本和依赖关系。

5.1 GetTypes():获取程序集中的所有类型。
5.2 GetExportedTypes():获取程序集中导出的所有类型。
5.3 Assembly.Load(byte[] assemblyName): 从指定的二进制数组加载程序集。
5.4 Assembly.LoadFile(string fileName): 从指定的文件加载程序集。
5.5 Assembly.GetExecutingAssembly(): 获取当前执行的程序集。

Assembly assembly = Assembly.Load("MyAssembly");

6、EventInfo 类

EventInfo 类用于操作事件。

6.1 EventInfo.AddEventHandler(object obj, Delegate handler): 订阅事件。
6.2 EventInfo.RemoveEventHandler(object obj, Delegate handler): 取消订阅事件。

EventInfo eventInfo = type.GetEvent("MyEvent");
eventInfo.AddEventHandler(myObject, new EventHandler(Handler));

7、FieldInfo 类

FieldInfo 类用于操作字段。

7.1 FieldInfo.GetValue(object obj): 获取字段的值。
7.2 FieldInfo.SetValue(object obj, object value): 设置字段的值。

FieldInfo fieldInfo = type.GetField("MyField");
fieldInfo.SetValue(myObject, value);

四、使用场景

1、动态类型创建: 当你需要根据字符串名称动态创建对象时,反射非常有用。例如,从配置文件加载类名并创建其实例。
2、对象浏览和修改: 反射可以用来动态地访问和修改对象的属性和字段,这对于开发诸如对象浏览器或编辑器的工具特别有用。
3、延迟绑定: 在不直接引用类型的情况下,调用其方法或属性。这对于插件或模块化架构特别重要,因为它允许运行时加载和使用模块。
4、自定义特性处理: 通过反射,可以在运行时查询自定义特性(Attribute),这对于实现各种框架功能(如序列化、ORM映射等)非常有用。

五、使用方法

1. 获取类型信息

要使用反射,首先需要获取目标类型的 Type 对象。有几种方法可以实现这一点:

// 直接通过类型获取Type对象
Type type1 = typeof(MyClass);// 通过对象实例获取Type对象
MyClass obj = new MyClass();
Type type2 = obj.GetType();// 通过字符串名称获取Type对象
string typeName = "Namespace.MyClass";
Type type3 = Type.GetType(typeName);

2. 创建对象实例

反射允许动态创建对象实例,即使在编译时不知道确切类型。

Type myType = Type.GetType("Namespace.MyClass");
object myObj = Activator.CreateInstance(myType);

3. 调用方法

通过反射,可以动态调用对象的方法。

MethodInfo methodInfo = myType.GetMethod("MethodName");
methodInfo.Invoke(myObj, new object[] { 参数列表 });

4. 访问字段和属性

获取类型后,可以使用Type.GetField()和Type.GetProperty()方法获取字段和属性,然后使用FieldInfo.GetValue()和PropertyInfo.GetValue()访问字段的值和属性的值。

// 获取并设置属性值
PropertyInfo propInfo = myType.GetProperty("PropertyName");
propInfo.SetValue(myObj, value, null);// 获取并设置字段值
FieldInfo fieldInfo = myType.GetField("FieldName");
fieldInfo.SetValue(myObj, value);

5. 处理自定义特性

反射可以用来查询和处理自定义特性。

Attribute[] attrs = Attribute.GetCustomAttributes(myType);
foreach(Attribute attr in attrs)
{if (attr is MyCustomAttribute){MyCustomAttribute myAttr = (MyCustomAttribute)attr;// 处理特性}
}

六、实际应用示例

假设我们有一个配置文件,指定了要创建和使用的类名。我们可以使用反射来动态加载类并调用其方法:

using System;
using System.Reflection;
class Program
{static void Main(){string className = "Namespace.MyClass"; // 通常从配置文件读取Type type = Type.GetType(className);if (type != null){object instance = Activator.CreateInstance(type);MethodInfo method = type.GetMethod("DoSomething");if (method != null){method.Invoke(instance, null);}}}
}

这个例子展示了如何根据配置动态实例化对象并调用其方法,这在开发需要高度模块化和可配置性的应用程序时非常有用。

七、反射的优缺点

优点:

  1. 提高程序的灵活性和可扩展性,使程序可以应对不同的场景。
  2. 支持动态生成代码,实现热插拔等功能。
  3. 简化开发人员对底层实现的操作,提高开发效率。

缺点:

  1. 性能开销:反射操作通常比直接的代码执行慢,因为需要在运行时解析类型信息。
  2. 安全性问题:反射允许程序在运行时修改自身结构,可能导致潜在的安全风险。

八、反射的注意事项

  1. 性能开销:反射操作通常比直接调用慢,因为它需要在运行时解析类型信息。应避免在性能敏感的代码段中使用反射。
  2. 安全性:反射允许程序在运行时修改自身结构,这可能导致安全风险。应确保只有可信代码使用反射。
  3. 类型正确性:在使用反射时,确保操作的类型是正确的,以避免类型转换异常。
  4. 避免不必要的反射:只在必要时使用反射,避免不必要的反射操作。

总结

C# 反射是一个强大的机制,它为动态类型处理、延迟绑定和运行时类型信息访问提供了广泛的支持。虽然反射可能会带来性能开销,但其灵活性和功能强大使其成为解决许多复杂编程问题的关键技术。了解和掌握反射的使用,可以大大提高C#程序的灵活性和可扩展性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/663794.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解C++中auto关键字

auto关键字 auto关键字(C11)类型别名思考auto简介auto的使用细则auto与指针和引用结合起来使用在同一行定义多个变量 auto不能推导的场景1.auto不能作为函数的参数2.auto不能直接用来声明数组 auto关键字(C11) 类型别名思考 随着程序越来越复杂,程序中用到的类型也…

山东淄博刑侦大队利用无人机抓获盗窃团伙

山东淄博刑侦大队利用无人机抓获盗窃团伙 近期,山东淄博临淄区发生多起盗窃案件。通过视频追踪和调查访问,推断临淄区某村可能为嫌疑人藏匿地点。刑侦大队无人机应急小组迅速到达现场,经无人机高空侦查,发现并锁定了嫌疑人的藏匿…

vue使用pdf.js实现在线查看pdf文件

需求&#xff1a;有一个列表页&#xff0c;用户点击查看&#xff0c;弹层展示后台接口返回的pdf内容(不是文件、地址之类的&#xff0c;乱码的pdf铭文(二进制文件流)) 1、pdf.js安装 npm install --save vue-pdf2、正文代码 <template><div><el-table :data&q…

SpringBoot+Vue使用AES进行接口加密

目录 前言 一、前端工作准备 1.下载crypto-js 2.加密解密工具类 3.对axios请求拦截加密 二、后端工作准备 1.所需依赖 2.实现RequestBodyAdvice 3.实现HttpInputMessage 三、数据响应加密&#xff08;扩展&#xff09; 1.实现 ResponseBodyAdvice&#xff08;后端&#xff…

【python】RGB色彩空间转Lab色彩空间

用于检验的网站&#xff1a;颜色空间转换 - 在线工具 (buyaocha.com) 单个输入 import numpy as npdef rgb_to_xyz(rgb):# 将RGB值转换为XYZ空间rgb np.array(rgb) / 255.0rgb np.where(rgb < 0.04045, rgb / 12.92, ((rgb 0.055) / 1.055) ** 2.4)rgb rgb.reshape((…

格式化内存卡后,如何找回丢失的监控视频?

随着摄像头的应用越来越广泛&#xff0c;很多监控摄像头采用了内存卡作为存储介质&#xff0c;方便用户存储和查看摄像头拍摄的视频文件。然而&#xff0c;由于各种原因&#xff0c;监控摄像头的内存卡有时会被意外格式化导致重要数据的丢失&#xff0c;给用户带来诸多困扰。 那…

SpringMVC请求和响应

文章目录 1、请求映射路径2、请求参数3、五种类型参数传递3.1、普通参数3.2、POJO类型参数3.3、嵌套POJO类型参数3.4、数组类型参数3.5、集合类型参数 4、json数据传递4.1、传递json对象4.2、传递json对象数组 5、日期类型参数传递6、响应6.1、响应页面6.2、文本数据6.3、json数…

PHP集成开发 -- PhpStorm 2023

PhpStorm 2023是一款强大的PHP集成开发环境&#xff08;IDE&#xff09;&#xff0c;旨在提高开发人员的生产力和代码质量。以下是关于PhpStorm 2023软件的详细介绍&#xff1a; 首先&#xff0c;PhpStorm 2023提供了丰富的代码编辑功能&#xff0c;包括语法高亮、自动补全、代…

【DDD】学习笔记-代码模型的架构决策

代码模型属于软件架构的一部分&#xff0c;它是设计模型的进化与实现&#xff0c;体现出了代码模块&#xff08;包&#xff09;的结构层次。在架构视图中&#xff0c;代码模型甚至会作为其中的一个视图&#xff0c;通过它来展现模块的划分&#xff0c;并定义运行时实体与执行视…

sklearn.preprocessing 标准化、归一化、正则化

文章目录 数据标准化的原因作用归一化最大最小归一化针对规模化有异常的数据标准化线性比例标准化法log函数标准化法正则化Normalization标准化的意义数据标准化的原因 某些算法要求样本具有零均值和单位方差;需要消除样本不同属性具有不同量级时的影响: ① 数量级的差异将导…

比较以下Unity AStar Pathfinding, NavMesh, Recast Navigation 寻路算法的优点与缺点

一、AStar Pathfinding AStar Pathfinding是一种基于图搜索的寻路算法&#xff0c;它使用启发式搜索来找到最短路径。AStar Pathfinding的优点包括&#xff1a; 高效性&#xff1a;AStar Pathfinding是一种高效的寻路算法&#xff0c;因为它使用启发式搜索来找到最短路径&…

【AudioPolicy To AudioHAL笔记(三)】安卓S上audio_policy_configuration.xml 加载过程分析

安卓S上audio_policy_configuration.xml 加载过程分析 /*****************************************************************************************************************/ 声明: 本博客内容均由https://blog.csdn.net/weixin_47702410原创&#xff0c;转载or引用请注明…

「效果图渲染」效果图与3D影视动画渲染平台

效果图渲染和3D影视动画渲染都是视觉图像渲染的领域应用。效果图渲染主要服务于建筑、室内设计和产品设计等行业&#xff0c;这些领域通常对视觉呈现的精度和细节有较高要求。与之相比&#xff0c;3D影视动画渲染则普遍应用于电影、电视、视频游戏和广告等媒体领域&#xff0c;…

LLM(3) | 自注意力机制 (self-attention mechanisms)

LLM(3) | 自注意力机制 (self-attention mechanisms) self-attention 是 transformer 的基础&#xff0c; 而 LLMs 大语言模型也都是 transformer 模型&#xff0c; 理解 self-attention, 才能理解为什么 LLM 能够处理好上下文关联性。 本篇是对于 Must-Read Starter Guide t…

题目: 有1234个数字, 组成多个互不相同且无重复数字的三位数? 都是多少?

lua脚本如下 最原始的解题方法 local str{} local i, j, k0, 0, 0 for i1, 4 do for j1, 4 do for k1, 4 do if i~j and i~k and j~k then str[#str1]i..j..k end end end end print("组成的数有"..#str) print(table.unpack(str)) 运行的结果如下 组成的数有24 1…

SpringbootWeb案例

准备工作 需求说明 部门管理 部门管理功能开发包括&#xff1a;查询部门列表、删除部门、新增部门、修改部门   员工管理功能开发包括&#xff1a;查询员工列表(分页、条件)、删除员工、新增员工、修改员工 环境搭建 环境搭建步骤&#xff1a;1. 准备数据库表(dept、emp)…

【Chrono Engine学习总结】2-可视化

由于Chrono的官方教程在一些细节方面解释的并不清楚&#xff0c;自己做了一些尝试&#xff0c;做学习总结。 0、基本概念 类型说明&#xff1a; Chrono的可视化包括两块&#xff1a;实时可视化&#xff0c;以及离线/后处理可视化。 其中&#xff0c;实时可视化&#xff0c;又…

获取ping值最小IP

有时候我们访问一个网站&#xff0c;想要选择最佳的IP地址&#xff0c;那就可能需要修改hosts文件。那么怎么获取最佳的IP地址呢&#xff0c;我们以访问github为例。 获取IP 首先是看对应的url会解析出哪些IP。可以在通过站长工具测试多个地点Ping服务器,网站测速 - 站长工具…

近期CCF系列会议截稿时间

专属领域会议订阅 关注{晓理紫}&#xff0c;每日更新会议信息&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 如果你感觉对你有所帮助&#xff0c;请关注我&#xff0c;每日准时为你推送最新会议信息。 CSFW (CCF B) IEEE Computer Security Foun…

Redis -- list列表

只有克服了情感的波动&#xff0c;才能专心致志地追求事业的成功 目录 列表 list命令 lpush lpushx rpush rpushx lrange lpop rpop lindex linsert llen lrem ltrim 阻塞命令 小结 列表 列表相当于 数组或者顺序表。 列表类型是用来存储多个有序的字符串&…