调试器数据模型 C++ 的其他接口

本主题介绍与调试器 C++ 数据模型关联的一些其他接口,例如元数据、概念和对象枚举。

调试器数据模型元数据接口

数据模型中的核心概念之一是,对象(尤其是合成对象)是键/值/元数据元组的字典。 每个键可以有一个完整的元数据存储,用于描述键及其潜在值周围的各种内容。 请注意,元数据不会以任何方式更改键的值。 只有与键及其值相关联的辅助信息才会影响键及其值的表示或其他相关属性。

从某种意义上说,元数据存储与数据模型中对象本质的键/值/元数据元组并没有太大不同。 然而,从这个角度来看,它被简化了。 元数据存储由 IKeyStore 接口表示。 虽然也是键/值/元数据元组的集合,但与模型对象相比,元数据键存储的功能存在局限性:

  • 一个键存储只能有一个父存储,而不能有任意的父模型链。
  • 键存储没有概念。 它只能有键/值/元数据元组的字典。 这意味着键存储中存在的键是静态的。 它们不能由动态语言系统按需创建。
  • 仅按照约定,元数据定义的键存储中的值仅限于基本值(内部函数和属性访问器)

虽然键存储可以具有任意数量(和任意命名)的键,但也有某些名称定义了语义值。 目前,这些名称为:

密钥名称 值类型 说明
PreferredRadix 整数:2、8、10 或 16 指示序号值应以何种基数显示
PreferredFormat 整数:由 PreferredFormat 枚举定义 指示显示值的首选格式类型
PreferredLength Integer 对于数组和其他容器,指示默认情况下应显示多少个元素
FindDerivation 布尔 指示调试主机在使用前是否应对值执行派生类型分析(例如:显示)
帮助 字符串 按键的工具提示样式帮助文本,可以通过用户界面以适当有用的方式呈现。
ActionName 字符串 指示给定的方法(不采用任何参数且不返回任何值)是一个操作。 操作的名称在元数据中指定。 用户界面可以利用此名称在上下文菜单或其他适当的界面中显示该选项
ActionIsDefault 布尔 仅当指定 ActionName 键时有效,指示这是对象的默认操作。
ActionDescription 字符串 仅当指定 ActionName 键时有效,这才为操作提供工具提示样式说明。 此类文本可以通过用户界面以适当有用的方式呈现。

请注意,虽然元数据存储中的键可以有自己的元数据 (ad infiniteum),但目前没有此类用途。 大多数调用方将为 IKeyStore 接口上的方法中的任何元数据参数指定 null。

核心元数据接口:IKeyStore

IKeyStore 接口定义如下:

DECLARE_INTERFACE_(IKeyStore, IUnknown)
{
   STDMETHOD(GetKey)(_In_ PCWSTR key, _COM_Errorptr_opt_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
   STDMETHOD(SetKey)(_In_ PCWSTR key, _In_opt_ IModelObject* object, _In_opt_ IKeyStore* metadata) PURE;
   STDMETHOD(GetKeyValue)(_In_ PCWSTR key, _COM_Errorptr_opt_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
   STDMETHOD(SetKeyValue)(_In_ PCWSTR key, _In_ IModelObject* object) PURE;
   STDMETHOD(ClearKeys)() PURE;
}

GetKey

GetKey 方法类似于 IModelObject 上的 GetKey 方法。 如果指定键存在于键存储或键存储的父存储中,它将返回指定键的值。 请注意,如果键的值是属性访问器,则不会在属性访问器上调用 GetValue 方法。 将返回装箱到 IModelObject 中的实际 IModelPropertyAccessor。 出于这个原因,客户端通常会调用 GetKeyValue。

SetKey

SetKey 方法类似于 IModelObject 上的 SetKey 方法。 它是唯一能够在键存储中创建键并将元数据与之关联的方法。

GetKeyValue

GetKeyValue 方法是客户端在元数据存储中查找特定键的值时将采用的第一种方法。 如果键参数指定的键存在于存储(或其父存储)中,则将返回该键的值以及与之关联的任何元数据。 如果键的值是属性访问器(装箱到 IModelObject 中的 IModelPropertyAccessor),则 GetKeyValue 将自动调用属性访问器的 GetValue 方法,并返回属性的基础值。

SetKeyValue

SetKeyValue 方法类似于 IModelObject 上的 SetKeyValue 方法。 此方法无法在元数据存储中创建新键。 如果键参数指示存在现有键,则会按指示设置其值。 如果键是属性访问器,则将在属性访问器上调用 SetValue 方法,以设置基础值。 请注意,元数据创建后通常是静态的。 很少在元数据键存储中使用此方法。

ClearKeys

ClearKeys 方法类似于 IModelObject 上的 ClearKeys 方法。 它将从给定的元数据存储中删除每个键。 此方法对任何父存储都没有任何影响。

数据模型中的对象枚举

枚举数据模型中的对象

数据模型中有两个核心键枚举接口:IKeyEnumerator 和 IRawEnumerator。 虽然这是两个核心接口,但它们可用于以三种样式之一枚举对象:

- 可以通过调用 EnumerateKeys 来获取 IKeyEnumerator 接口,以便枚举对象的键及其值/元数据,而无需解析任何基础属性访问器。 此枚举样式可以返回装箱到 IModelObjects 的原始 IModelPropertyAccessor 值。

- 可以通过调用 EnumerateKeyValues 或 EnumerateRawValues 来获取 IKeyEnumerator 和 IRawEnumerator 接口,以便枚举对象的键/原始值及其值/元数据。 枚举中存在的任何属性访问器都会在枚举过程中通过调用基础 GetValue 方法自动解析。

引用 - 可以通过调用 EnumerateKeyReferences 或 EnumerateRawReferences 来获取 IKeyEnumerator 和 IRawEnumerator 接口,以便枚举对对象上键/原始值的引用。 可以保存这些引用,并在以后用于获取或设置基础键或原始值。

KeyEnumerator:合成键的枚举

IKeyEnumerator 接口是用于枚举实例对象内的所有键(按键、值或引用)及其父模型链中所有关联的父模型的单个接口。 接口定义如下:

DECLARE_INTERFACE_(IKeyEnumerator, IUnknown)
{
    STDMETHOD(Reset)() PURE;
    STDMETHOD(GetNext)(_Out_ BSTR* key, _COM_Errorptr_opt_ IModelObject** value, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
}

重置

Reset 方法将枚举器重置为首次获取枚举器时所处的位置(例如:在枚举中的第一个元素之前)。 对 GetNext 的后续调用将返回第一个枚举键。

GetNext

GetNext 方法既向前移动枚举器,又返回枚举中该位置的键。

IRawEnumerator:枚举本机语言或基础语言 (C/C++) 构造

IRawEnumerator 接口是用于枚举对象内所有本机/语言构造(按值或引用)的单个接口,该对象表示调试目标地址空间内的本机构造。 接口定义如下:

DECLARE_INTERFACE_(IRawEnumerator, IUnknown)
{
    STDMETHOD(Reset)() PURE;
    STDMETHOD(GetNext)(_Out_opt_ BSTR* name, _Out_opt_ SymbolKind *kind, _COM_Errorptr_opt_ IModelObject** value) PURE;
}

重置

Reset 方法将枚举器重置为首次获取枚举器时所处的位置(例如:在枚举中的第一个元素之前)。 对 GetNext 的后续调用将返回第一个枚举的本机/语言构造。

GetNext

GetNext 方法既向前移动枚举器,又返回枚举中该位置的本机/语言构造。


另请参阅

本专题是系列专题的一部分,主要介绍 C++ 可访问的接口、如何使用这些接口构建基于 C++ 的调试器扩展,以及如何通过 C++ 数据模型扩展使用其他数据模型构造(如 JavaScript 或 NatVis)。

调试器数据模型 C++ 概述

调试器数据模型 C++ 接口

调试器数据模型 C++ 对象

调试器数据模型 C++ 的其他接口

调试器数据模型 C++ 的概念

调试器数据模型 C++ 脚本