C#的反射(Reflection)与特性(Attribute)

25 年 4 月 1 日 星期二
895 字
5 分钟

基本概念梳理

反射 (Reflection) 是一种编程机制,允许程序在运行时动态地检查和操作自身的结构和行为。这个概念不是指任何代码中的数据类型或是关键字,而是一个抽象出来的编程机制。也就是说,使得程序能够在运行期间获取对象方法属性等信息,并能够动态地调用方法创建实例修改属性的这些个特点被称为反射。

在小型项目开发中,因为项目系统复杂度较低,反射的应用场景比较有限。 反射通常可以用于:编辑器扩展序列化/反序列化热更新等相关的需求。此外,值得一提的是Unity引擎底层的不少功能实现也是基于反射机制。


特性 (Attribute) 本质上是一个C#的类,我们可以使用这个类型来向程序集直接添加特定元数据以在对象方法属性等代码结构上标注特定信息。这些标注既不属于任何数据类型或关键字,也不会直接影响代码的逻辑执行,但在编译或运行时可以通过反射等方式被读取和解析,从而指导程序的特定行为或配置。


相关要点

反射的原理

mermaid
flowchart LR
    C["C#源代码"]
    C --> D["编译器编译<br/>DLL / EXE"]
    D --> G["元数据(Metadata)"]
    G --> E["公共语言运行时(CLR)<br/>即时或提前编译(JIT/AOT)"]
    E --> F["二进制机器码<br/>01010101"]
    D --> H["中间语言(IL)"]
	H --> E

从编译运行的流程上来看,C# 源代码首先由编译器转换为中间语言 (IL),然后由公共语言运行时 (CLR) 进行加载和即时编译 (JIT),最终在运行时执行并支持反射。再具体来说,.NET 应用程序是由程序集 (Assembly)模块 (Module)类型 (Class) 等部分组成的。而反射就是在运行时通过读取编译后程序集中的元数据 (Metadata) 来获取这些类型定义信息,从而在运行时实现动态操作。

Unity中的C#脚本编译过程会略有不同,取决于使用的解决方案。 像是IL2CPP或是启用Burst编译优化的话就比较特殊,详见DWHITE/3_编程与开发/Unity/Unity_CSharp脚本的编译运行

反射的优缺点

优点缺点
提高程序的灵活性与扩展性。性能问题:反射本质上是一种解释操作,需要进行字符串匹配等,用于字段与方法接入时将远慢于直接的编译期绑定方式。
降低代码的耦合性,提高自适应能力。可读性与维护难度:反射的运用会使得部分程序逻辑被“隐藏”,调用链条不直观,调试时难以从源代码中直接预期逻辑如何发生。
使得程序能够创建和控制任何类的对象,而无需提前硬编码目标。安全性问题:通过反射可访问私有成员、破坏封装,若管理不当会造成敏感数据泄露或其他安全风险。
可在运行时动态检查或修改类的结构信息。潜在兼容性风险:过度依赖运行时的类名、方法名字符串,若类或方法被重命名或移除,则可能在反射调用处引发 ClassNotFoundExceptionNoSuchMethodException 等错误。

文章标题:C#的反射(Reflection)与特性(Attribute)

文章作者:DWHITE

文章链接:https://dr9k69ai79.github.io/MyBlog/posts/csharp_反射reflection与特性attribute[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。