3.0 KiB
3.0 KiB
MonoScriptRuntime::TryGetClassFieldMetadata
命名空间: XCEngine::Scripting
类型: method
头文件: XCEngine/Scripting/Mono/MonoScriptRuntime.h
签名
bool TryGetClassFieldMetadata(
const std::string& assemblyName,
const std::string& namespaceName,
const std::string& className,
std::vector<ScriptFieldMetadata>& outFields) const override;
作用
返回指定脚本类当前“可进入字段模型”的字段元数据列表。
这里返回的不是类里声明的全部字段,而是经过 Mono 运行时筛选后的字段集合。
当前实现行为
- 先清空
outFields。 - 用
(assemblyName, namespaceName, className)查缓存里的类元数据。 - 如果类不存在,返回
false,并保持outFields为空。 - 如果类存在:
- 遍历
metadata->fields - 复制成
ScriptFieldMetadata{name, type} - 最终按字段名排序后返回
true
- 遍历
因此,这个方法本身不再扫描程序集;它只读取初始化阶段已经构建好的类缓存。
字段筛选规则
字段集合来源于 DiscoverScriptClassesInImage(...) 的筛选结果。当前真实规则是:
- 排除
static - 排除
const / literal - 排除
readonly / init-only - 接受:
public实例字段- 或带
[SerializeField]的private实例字段
- 再要求字段类型属于当前支持集合
这意味着“private”本身不是问题,问题在于它有没有显式进入序列化/字段模型。
典型例子
managed/GameScripts/FieldMetadataProbe.cs 当前很好地展示了这些边界:
- 会被发现:
HealthSpeedLabelSpawnPointStateTargetHiddenFlag
- 不会被发现:
SharedCounterIgnoredPrivateCounterUnsupportedRotation
其中 HiddenFlag 能被发现,正是因为它是 [SerializeField] private bool。
为什么这很重要
这条规则直接决定了:
- Inspector / 字段编辑 UI 能看到哪些字段
- 场景序列化允许存哪些字段
- 运行时字段默认值和字段同步覆盖哪些字段
如果一个字段没进入这里,它后续也不会出现在 TryGetClassFieldDefaultValues 或字段同步链里。
返回值语义
true- 类存在;即使类存在但筛完没有可用字段,也仍然可能返回
true且outFields为空。
- 类存在;即使类存在但筛完没有可用字段,也仍然可能返回
false- 类不存在,无法找到对应类元数据。
测试锚点
tests/Scripting/test_mono_script_runtime.cpp 里的
ClassFieldMetadataListsSupportedPublicInstanceFields
已经明确验证:HiddenFlag 会进入字段元数据,而未标注 private 字段不会。