编辑
2023-07-03
编程语言
00

目录

一、程序集(Assembly)
概念
Unity 中程序集的生成与划分规则
编译行为总结
二、元数据(Metadata)
概念
包含内容
作用
三、反射(Reflection)
概念
常见用途
使用流程图
四、典型应用场景
五、关键词速查
六、反射 API 实战与常见用法
获取类型信息
动态创建实例
获取字段并访问
获取属性并访问
获取方法并调用
获取构造函数并调用
遍历字段/属性/方法
获取特性
加载外部程序集并实例化类型
七、API 快速查阅表
八、总结

一、程序集(Assembly)

概念

  • 程序集是 C# 编译后的最终产物,通常是 .dll.exe 文件。
  • 它包含:
    • IL 中间语言代码
    • 元数据(Metadata)
    • 清单(程序集信息)
    • 可选资源文件

Unity 中程序集的生成与划分规则

文件夹路径是否编译生成的程序集名称
Assets/Scripts/Assembly-CSharp.dll(主逻辑)
Assets/Plugins/Assembly-CSharp-firstpass.dll
Assets/Editor/Assembly-CSharp-Editor.dll
使用 .asmdef 自定义目录自定义模块程序集(如 Game.UI.dll

编译行为总结

  • Unity 编译不是全量,而是按“程序集单位”增量编译;
  • .asmdef 可手动拆分模块,提升编译效率与解耦性;
  • 所有程序集输出至 Library/ScriptAssemblies/ 目录。

二、元数据(Metadata)

概念

  • 元数据是记录代码结构的信息,用于描述程序集中的类型、字段、方法、特性等;
  • 每个类的结构都会以元数据形式写入 .dll 中;

包含内容

元数据项示例
类型名public class Player
字段信息public int HP
方法签名public void Move(float spd)
特性(Attribute)[Serializable]
参数/返回类型等用于反射调用或自动匹配

作用

  • CLR 用于代码执行;
  • 反射 API 获取结构信息;
  • 支持序列化、自动绑定、调试等功能。

三、反射(Reflection)

概念

  • 反射是在运行时动态读取类型信息(元数据)并操作其字段、方法、属性的机制;
  • 本质:通过读取程序集的元数据,实现对类型的动态操作;

常见用途

用途示例
动态创建对象Activator.CreateInstance(type)
获取字段/方法信息type.GetField("Name")
调用方法method.Invoke(obj, null)
获取/设置字段值field.GetValue(obj) / SetValue(...)
获取自定义特性GetCustomAttribute<T>()

使用流程图

Assembly.Load("xxx.dll") ↓ GetType("命名空间.类名") ↓ 构建 Type/FieldInfo/MethodInfo ↓ 动态创建对象 / 获取字段 / 调用方法

四、典型应用场景

场景使用反射使用元数据说明
热更新框架(ILRuntime)动态加载、调用模块
导表工具(JSON映射)自动字段绑定无需硬编码
插件系统/自动注册自动注册模块,减少手工操作
编辑器工具生成自动化生成 Inspector 字段列表
特性驱动的行为扩展利用 Attribute 实现数据驱动

五、关键词速查

关键词含义
Assembly程序集,最终产物 .dll/.exe
Metadata记录程序结构的描述信息,写入程序集内部
Reflection运行时动态获取类型信息、字段、方法等操作
.csproj告诉编译器哪些文件组成项目,如何编译生成程序集
.asmdefUnity 中手动拆分程序集的配置文件
IL中间语言代码(Intermediate Language)

六、反射 API 实战与常见用法

获取类型信息

csharp
Type type = typeof(MyClass); Type type2 = obj.GetType();

动态创建实例

csharp
object obj = Activator.CreateInstance(type);

带参数构造函数:

csharp
object obj = Activator.CreateInstance(type, new object[] { "Tom", 18 });

获取字段并访问

csharp
FieldInfo field = type.GetField("name"); object value = field.GetValue(obj); field.SetValue(obj, "NewName");

访问私有字段:

csharp
var field = type.GetField("hp", BindingFlags.NonPublic | BindingFlags.Instance);

获取属性并访问

csharp
var prop = type.GetProperty("Score"); var val = prop.GetValue(obj); prop.SetValue(obj, 99);

获取方法并调用

csharp
var method = type.GetMethod("Attack"); method.Invoke(obj, new object[] { 10 });

获取构造函数并调用

csharp
var ctor = type.GetConstructor(Type.EmptyTypes); var obj = ctor.Invoke(null);

遍历字段/属性/方法

csharp
foreach (var f in type.GetFields()) Console.WriteLine(f.Name);

获取特性

csharp
var attr = field.GetCustomAttribute<ObsoleteAttribute>(); if (attr != null) Console.WriteLine("该字段已过时");

加载外部程序集并实例化类型

csharp
var asm = Assembly.LoadFrom("MyLib.dll"); var type = asm.GetType("MyLib.Foo"); var obj = Activator.CreateInstance(type);

七、API 快速查阅表

功能常用 API
获取类型typeof(T) / obj.GetType()
创建实例Activator.CreateInstance(type)
获取字段/属性/方法GetField() / GetProperty() / GetMethod()
批量获取GetFields() / GetMethods()
访问字段/属性值GetValue() / SetValue()
调用方法Invoke()
获取构造函数GetConstructor() / ConstructorInfo.Invoke()
加载程序集Assembly.Load() / LoadFrom()
获取特性(Attribute)GetCustomAttribute<T>()

八、总结

什么是反射?

反射是 C# 中一种运行时机制,它允许程序在不知道类型定义的情况下,动态获取类型信息、创建对象、访问字段、调用方法

反射的原理是?

C# 编译后生成的程序集(DLL 或 EXE)中包含了类型的元数据,这些元数据记录了类的结构(包括字段、属性、方法、特性等)。 运行时通过 .NET 提供的 System.Reflection 命名空间读取这些元数据,并通过 Type、FieldInfo、MethodInfo 等对象实现动态操作。

本文作者:xuxuxuJS

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!