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