Zongsoft.Reflection
Zongsoft.Reflection 的反射访问、动态访问器和成员表达式求值能力。
Zongsoft.Reflection 为运行时对象访问提供一组轻量反射工具。它把常见的字段、属性、索引器和成员路径访问封装成可复用的动态访问器模型,适合配置绑定、数据映射、模板求值、命令参数解析、插件扩展和其他“成员名称在运行时才确定”的场景。
反射访问本身不应替代普通的强类型代码:当成员在编译期已经确定时,直接调用仍然是最清晰的写法;当字段名、属性名或访问路径来自配置、脚本、用户输入或元数据时,再使用本命名空间提供的能力。
主要职责
通过
Reflector统一读取和写入字段、属性以及索引器。通过
System.Reflection.Emit为 System.Reflection.FieldInfo 和 System.Reflection.PropertyInfo 动态编译并缓存 getter、setter 访问器,减少重复反射调用的成本。支持按字符串成员名读取或写入对象成员,名称查找忽略大小写,并可访问默认成员。
解析成员表达式,将
Address.City、Items[0].Name、Get("key")这类路径转换为表达式节点链。通过
MemberExpressionEvaluator对表达式进行求值或设置最终成员。为模型映射、数据绑定、配置绑定、序列化、报表字段选择等模块提供底层成员访问能力。
核心类型
Reflector
高层反射访问入口。
按 System.Reflection.MemberInfo 或字符串成员名读取、写入字段和属性。
FieldInfoExtension
字段访问器扩展。
从 System.Reflection.FieldInfo 获取缓存的 getter、setter。
PropertyInfoExtension
属性访问器扩展。
从 System.Reflection.PropertyInfo 获取缓存的 getter、setter,并支持索引器参数。
MemberExpression
成员表达式基类和解析入口。
解析或手动构造成员路径表达式。
IMemberExpression
表达式节点接口。
表示表达式链中的一个节点,并通过 Previous、Next 串联。
IdentifierExpression
标识符节点。
表示普通字段或属性名。
IndexerExpression
索引器节点。
表示 [] 访问,并携带索引参数。
MethodExpression
方法节点。
表示方法调用和参数列表。
ConstantExpression
常量节点。
表示字符串、数字和空值等参数值。
MemberExpressionEvaluator
表达式求值器。
对目标对象读取路径值,或写入路径末端成员。
成员访问
Discussions 没有直接调用 Reflector;它通过映射与配置间接使用这些机制。本页从 核心类库 的现有测试读取 API 形状,其中 MyValue、ClassEntity 都是测试夹具类型。
Reflector 是最常用的入口。它既可以接收已经解析好的 System.Reflection.MemberInfo,也可以直接按成员名称查找对象的公开字段或属性。
来源:framework/Zongsoft.Core/test/Reflection/ReflectorTest.cs(节选;上下文见源文件)。
GetValue、SetValue 会在目标为空、成员不存在、属性不可读等情况下抛出异常;写入只会对可写属性和非只读字段生效,遇到只读字段或不可写属性时会返回 false。TryGetValue、TrySetValue 更适合处理外部输入、可选字段或兼容旧模型的场景。
如果调用方已经持有 System.Reflection.FieldInfo、System.Reflection.PropertyInfo 或 System.Reflection.MemberInfo,可以直接使用扩展方法。GetGetter/GetSetter 会复用缓存。下面的测试则显式调用 GenerateGetter/GenerateSetter,以验证动态访问器生成与读写结果;不要在热循环中反复 Generate。
来源:framework/Zongsoft.Core/test/Reflection/PropertyInfoTest.cs(节选;上下文见源文件)。
动态访问器与性能
字段和属性扩展方法内部会基于 System.Reflection.Emit 生成动态方法,再把动态方法编译成 getter 或 setter 委托。第一次访问某个成员时需要完成动态方法生成、IL 发射和委托创建;生成完成后,访问器会缓存在成员信息对应的缓存项中,后续读取或写入同一成员时直接调用委托,避免反复走传统反射的 GetValue、SetValue 路径。
这种设计适合高频、重复的运行时成员访问:例如数据映射持续填充模型、配置绑定反复写入属性、模板或报表按字段名读取对象。它不会让一次性的成员查找变成强类型调用,也不能消除按名称查找成员、解析表达式和参数转换的成本;因此在循环或批处理场景中,应尽量复用已经取得的 System.Reflection.FieldInfo、System.Reflection.PropertyInfo 或解析后的表达式对象。
源码仓库的 Zongsoft.Core/benchmark/Reflection 目录提供了属性读写的 BenchmarkDotNet 基准测试。测试以普通反射的 PropertyInfo.GetValue、PropertyInfo.SetValue 为基线,分别比较 Reflector 封装访问和直接复用 GetGetter<T>、GetSetter<T> 委托的路径;实际收益取决于运行时、成员形状和调用次数,应在目标环境测量,不能仅凭存在基准项目就推断具体倍数。
索引器访问
属性访问器支持索引参数,因此既可以通过具体的 System.Reflection.PropertyInfo 调用,也可以通过默认成员访问索引器。
ReflectorTest.TestValueType 已在上面的片段中读取 Item 索引器的 0 至 4 项。MyValue 的索引器与字段定义保存在同一测试文件中,复用时应保留该夹具;索引越界和参数类型错误仍由目标成员决定。
这类写法适合处理集合、字典、动态模型或带默认成员的对象。对于字典、集合这样的强类型代码路径,如果键和索引在编译期已知,直接访问集合通常更直观。
成员表达式
Zongsoft.Reflection.Expressions 子命名空间提供成员路径解析和求值能力。表达式会被解析为一条双向节点链,每个节点代表一次成员、方法或索引器访问。
来源:framework/Zongsoft.Plugins/src/Configuration/OptionParser.cs(节选;上下文见源文件)。
上面是插件 option 表达式的实际求值入口:先按配置路径取得对象,有附加成员路径时才交给 MemberExpressionEvaluator。后面的表格是语法形式参考,不表示 Discussions 模型具有这些属性。
常见表达式形态如下:
Name
读取目标对象的 Name 字段或属性。
Address.City
逐级读取嵌套成员。
Items[0]
访问默认索引器的第一个元素。
Items[0].Name
先取集合元素,再读取元素成员。
Options["theme"]
使用字符串常量作为索引器参数。
GetValue("name")
调用公开方法,并传入字符串常量参数。
GetItem(Index).Name
方法或索引器参数也可以是另一个成员表达式。
表达式参数支持单引号或双引号字符串、数字常量和成员表达式。数字常量从数字开始,可使用 L、F、M 后缀表示长整型、单精度或十进制数;包含小数点的数字会按双精度解析。
自定义求值
MemberExpressionEvaluator 的读取和写入方法都接受求值回调。回调会在每个节点解析到成员后执行,调用方可以检查当前节点、目标对象、成员信息和参数,也可以提前设置节点值,从而覆盖默认反射求值逻辑。
框架 Criteria.Transform 是实际的自定义写入调用点:它将查询成员名解析为路径,再按目标成员类型把文本转成布尔值、数组、集合或标量,通过 valueFactory 返回最终写入值。处理嵌套成员时,还用 evaluate 回调准备中间对象。完整流程见条件与操作元。
这适合实现默认值补齐、权限过滤、外部字典取值、惰性加载或对某些路径节点进行特殊映射。回调只应处理确实需要介入的节点;普通成员访问交给默认求值器即可。
使用建议
优先把反射访问限制在系统边界,例如配置、插件、映射、绑定、序列化、报表字段和命令参数处理。业务核心流程如果可以用接口、泛型或普通属性访问表达,就不必引入成员名字符串。
重复执行的路径建议先解析并缓存 IMemberExpression,不要在循环中反复调用 MemberExpression.Parse。同样地,已经拿到 System.Reflection.FieldInfo 或 System.Reflection.PropertyInfo 时,优先复用它们的动态访问器,而不是每次都按字符串名称查找。
来自用户输入或外部配置的成员路径应先做白名单校验。反射工具可以降低调用成本,但不会自动判断某个成员是否适合暴露给外部使用;暴露字段路径、方法调用或索引器访问时,应由调用方定义清晰的可访问范围。
子命名空间
Zongsoft.Reflection.Expressions
成员路径表达式解析、表达式节点模型和表达式求值器。
相关资源
最后更新于