Поделиться через


Объекты C++ модели данных отладчика

В этом разделе описывается, как использовать объекты C++ модели данных отладчика и как они могут расширить возможности отладчика.

Базовая объектная модель отладчика

Одним из самых простых, но мощных вещей в модели данных является то, что он стандартизирует определение того, что является объектом, и как он взаимодействует с объектом. Интерфейс IModelObject инкапсулирует понятие объекта, будь то целое число, значение с плавающей запятой, строка, некоторый сложный тип в целевом адресном пространстве отладчика или некоторые понятия отладчика, такие как понятие процесса или модуля.

Существует несколько разных вещей, которые можно хранить в (или боксировать в) IModelObject:

  • Встроенные значения — IModelObjectможет быть контейнером для ряда основных типов: 8, 16, 32 или 64-разрядных целых чисел, логических значений, строк, ошибок или понятия пустых.

  • Собственные объекты — IModelObjectможет представлять сложный тип (как определено системой типов отладчика) в адресном пространстве независимо от целевого объекта отладчика.

  • Искусственные объектыIModelObject может быть динамическим объектом— словарем, если вы будете: коллекция ключей и значений/ кортежей метаданных и набор понятий , определяющих поведение, которое не просто представлено парами "ключ - значение".

  • Свойства — IModelObject может представлять свойство: что-то, значение которого можно получить или изменить с помощью вызова метода. Свойство в IModelObject является фактически интерфейсом IModelPropertyAccessor, размещенным в IModelObject

  • Методы — IModelObjectможет представлять метод: то, что можно вызвать с набором аргументов и получить возвращаемое значение. Метод в IModelObject является фактически интерфейсом IModelMethod, размещенным в IModelObject

Расширяемость в объектной модели

IModelObject не является объектом в изоляции. Помимо представления одного из типов объектов, показанных выше, каждый объект имеет представление о цепочке родительских моделей данных. Эта цепочка ведет себя так же, как цепочка прототипов JavaScript. Вместо линейной цепочки прототипов, таких как JavaScript, каждый объект модели данных определяет линейную цепочку родительских моделей. Каждая из этих родительских моделей в свою очередь имеет другую линейную цепочку собственных наборов родителей. В сущности, каждый объект является агрегированием возможностей (свойств и т. д.) как самого, так и каждого объекта в этом дереве. При запросе определенного свойства, если объект, на который он запрашивается, не поддерживает это свойство, запрос передается в линейном порядке каждому родительскому элементу в свою очередь. Это создает поведение, в котором поиск свойства разрешается путем поиска по глубине дерева агрегата.

Расширяемость в этой объектной модели очень проста, учитывая это понятие, что каждый объект является агрегатом самого себя и дерева родительских моделей. Расширение может входить и добавляться в список родительских моделей для другого объекта. Это расширяет объект. Таким образом, можно добавить возможности на все: конкретный экземпляр объекта или значения, собственный тип, понятие отладчика о том, что такое процесс или поток, или даже понятие "все итерируемые объекты".

Контекст, контекст и контекст: этот указатель, адресное пространство и частные данные реализации

Существует три понятия контекста, которые необходимы для понимания в контексте объектной модели.

Контекст: этот указатель

Так как данное свойство или метод может быть реализовано на любом уровне дерева модели данных, необходимо для реализации метода или свойства, чтобы получить доступ к исходному объекту (то, что можно вызвать этот указатель в C++ или этот объект в JavaScript. Этот объект экземпляра передается различным методам в качестве первого аргумента, называемого контекстом в описанных методах.

Контекст: адресное пространство

Важно отметить, что в отличие от предыдущих моделей расширений, где контекст (целевой, процесс, поток, который вы просматриваете) представляет собой концепцию пользовательского интерфейса со всеми API относительно текущего состояния пользовательского интерфейса, интерфейсы модели данных обычно принимают этот контекст явно или неявно в качестве интерфейса IDebugHostContext . Каждый объект IModelObject в модели данных несет этот тип контекстной информации вместе с ним и может распространять этот контекст на объекты, возвращаемые им. Это означает, что при чтении собственного значения или значения ключа из IModelObject он будет считывать из целевого объекта и обрабатывать, откуда объект был первоначально получен.

Существует явное значение константы, USE_CURRENT_HOST_CONTEXT, которое можно передать в методы, которые принимают аргумент IDebugHostContext . Это значение указывает, что контекст действительно должен быть текущим состоянием пользовательского интерфейса отладчика. Однако это понятие должно быть явным.

Контекст. Реализация частных данных

Помните, что каждый объект в модели данных фактически является агрегатом экземпляра объекта и дерева родительских моделей, которые присоединены. Каждая из этих родительских моделей (которые могут быть связаны в цепочках множества различных объектов) может связывать данные частной реализации с любым объектом экземпляра. Каждый объект IModelObject , созданный концептуально, содержит хэш-таблицу, которая сопоставляется с определенной родительской моделью с данными частного экземпляра, определенными интерфейсом IUnknown . Это позволяет родительской модели кэшировать сведения на каждом экземпляре или содержать произвольные данные.

Доступ к этому типу контекста осуществляется с помощью методов GetContextForDataModel и SetContextForDataModel в IModelObject.

Интерфейс объекта Core Debugger: IModelObject


Интерфейс IModelObject определяется следующим образом:

DECLARE_INTERFACE_(IModelObject, IUnknown)
{
    STDMETHOD(QueryInterface)(_In_ REFIID iid, _COM_Outptr_ PVOID* iface);
    STDMETHOD_(ULONG, AddRef)();
    STDMETHOD_(ULONG, Release)() PURE;
    STDMETHOD(GetContext)(_COM_Outptr_result_maybenull_ IDebugHostContext** context) PURE;
    STDMETHOD(GetKind)(_Out_ ModelObjectKind *kind) PURE;
    STDMETHOD(GetIntrinsicValue)(_Out_ VARIANT* intrinsicData);
    STDMETHOD(GetIntrinsicValueAs)(_In_ VARTYPE vt, _Out_ VARIANT* intrinsicData) 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_opt_ IModelObject* object) PURE;
    STDMETHOD(EnumerateKeyValues)(_COM_Outptr_ IKeyEnumerator** enumerator) PURE;
    STDMETHOD(GetRawValue)(_In_ SymbolKind kind, _In_ PCWSTR name, _In_ ULONG searchFlags, _COM_Errorptr_ IModelObject** object) PURE;
    STDMETHOD(EnumerateRawValues)(_In_ SymbolKind kind, _In_ ULONG searchFlags, _COM_Outptr_ IRawEnumerator** enumerator) PURE;
    STDMETHOD(Dereference)(_COM_Errorptr_ IModelObject** object) PURE;
    STDMETHOD(TryCastToRuntimeType)(_COM_Errorptr_ IModelObject** runtimeTypedObject) PURE;
    STDMETHOD(GetConcept)(_In_ REFIID conceptId, _COM_Outptr_ IUnknown** conceptInterface, _COM_Outptr_opt_result_maybenull_ IKeyStore** conceptMetadata) PURE;
    STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
    STDMETHOD(GetTypeInfo)(_Out_ IDebugHostType** type) PURE;
    STDMETHOD(GetTargetInfo)(_Out_ Location* location, _Out_ IDebugHostType** type) PURE;
    STDMETHOD(GetNumberOfParentModels)(_Out_ ULONG64* numModels) PURE;
    STDMETHOD(GetParentModel)(_In_ ULONG64 i, _COM_Outptr_ IModelObject **model, _COM_Outptr_result_maybenull_ IModelObject **contextObject) PURE;
    STDMETHOD(AddParentModel)(_In_ IModelObject* model, _In_opt_ IModelObject* contextObject, _In_ bool override) PURE;
    STDMETHOD(RemoveParentModel)(_In_ IModelObject* model) PURE;
    STDMETHOD(GetKey)(_In_ PCWSTR key, _COM_Errorptr_opt_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
    STDMETHOD(GetKeyReference)(_In_ PCWSTR key, _COM_Errorptr_opt_ IModelObject** objectReference, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
    STDMETHOD(SetKey)(_In_ PCWSTR key, _In_opt_ IModelObject* object, _In_opt_ IKeyStore* metadata) PURE;
    STDMETHOD(ClearKeys)() PURE;
    STDMETHOD(EnumerateKeys)(_COM_Outptr_ IKeyEnumerator** enumerator) PURE;
    STDMETHOD(EnumerateKeyReferences)(_COM_Outptr_ IKeyEnumerator** enumerator) PURE;
    STDMETHOD(SetConcept)(_In_ REFIID conceptId, _In_ IUnknown* conceptInterface, _In_opt_ IKeyStore* conceptMetadata) PURE;
    STDMETHOD(ClearConcepts)() PURE;
    STDMETHOD(GetRawReference)(_In_ SymbolKind kind, _In_ PCWSTR name, _In_ ULONG searchFlags, _COM_Errorptr_ IModelObject** object) PURE;
    STDMETHOD(EnumerateRawReferences)(_In_ SymbolKind kind, _In_ ULONG searchFlags, _COM_Outptr_ IRawEnumerator** enumerator) PURE;
    STDMETHOD(SetContextForDataModel)(_In_ IModelObject* dataModelObject, _In_ IUnknown* context) PURE;
    STDMETHOD(GetContextForDataModel)(_In_ IModelObject* dataModelObject, _Out_ IUnknown** context) PURE;
    STDMETHOD(Compare)(_In_ IModelObject* other, _COM_Outptr_opt_result_maybenull_ IModelObject **ppResult) PURE;
    STDMETHOD(IsEqualTo)(_In_ IModelObject* other, _Out_ bool* equal) PURE;
}

Основные методы

Ниже приведены общие методы, применимые к любому типу объекта, представленного IModelObject.

STDMETHOD(GetKind)(_Out_ ModelObjectKind *kind) PURE;
STDMETHOD(GetContext)(_COM_Outptr_result_maybenull_ IDebugHostContext** context) PURE;
STDMETHOD(GetIntrinsicValue)(_Out_ VARIANT* intrinsicData);
STDMETHOD(GetIntrinsicValueAs)(_In_ VARTYPE vt, _Out_ VARIANT* intrinsicData) PURE;
STDMETHOD(Compare)(_In_ IModelObject* other, _COM_Outptr_opt_result_maybenull_ IModelObject **ppResult) PURE;
STDMETHOD(IsEqualTo)(_In_ IModelObject* other, _Out_ bool* equal) PURE;
STDMETHOD(Dereference)(_COM_Errorptr_ IModelObject** object) PURE;

GetKind

Метод GetKind возвращает тип объекта, размещенного внутри IModelObject.

GetContext

Метод GetContext возвращает контекст узла, связанный с объектом.

GetIntrinsicValue

Метод GetIntrinsicValue возвращает вещь, которая находится в контейнере IModelObject. Этот метод может вызываться только в интерфейсах IModelObject, представляющих встроенный интерфейс или определенный интерфейс, который установлен. Его нельзя вызывать на собственных объектах, без объектов значений, синтетических объектов и ссылочных объектов. Метод GetIntrinsicValueAs ведет себя так же, как метод GetIntrinsicValue, за исключением того, что он преобразует значение в указанный тип варианта. Если преобразование невозможно выполнить, метод возвращает ошибку.

IsEqualTo

Метод IsEqualTo сравнивает два объекта модели и возвращает, равны ли они в значении. Для объекта, который имеет упорядочение, этот метод, возвращающий true, эквивалентен методу Compare, возвращающим 0. Для объектов, у которых нет упорядочения, но являются приключаемыми, метод Compare завершится ошибкой, но это не будет. Значение сравнения на основе значений определяется типом объекта. В настоящее время это определяется только для встроенных типов и объектов ошибок. Нет текущей концепции модели данных для приравниваемости.

Dereference

Метод dereference разыменовывает объект. Этот метод можно использовать для расшифровки ссылки на модель данных (ObjectTargetObjectReference, ObjectKeyReference) или ссылки на собственный язык (указатель или справочник по языку). Важно отметить, что этот метод удаляет один уровень семантики ссылок на объект. Например, можно получить ссылку на модель данных на ссылку на язык. В таком случае вызов метода dereference в первый раз удалит ссылку на модель данных и оставьте ссылку на язык. Вызов деreference для этого результирующего объекта впоследствии удаляет ссылку на язык и возвращает собственное значение в этой ссылке.

Методы манипуляции ключами

Любой искусственный объект, являющийся словарем ключей, значений и кортежей метаданных, имеет ряд методов для управления этими ключами, значениями и метаданными, связанными с ними.

Ниже приведены формы на основе значений API:

STDMETHOD(GetKeyValue)(_In_ PCWSTR key, _COM_Errorptr_opt_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
STDMETHOD(SetKeyValue)(_In_ PCWSTR key, _In_opt_ IModelObject* object) PURE;
STDMETHOD(EnumerateKeyValues)(_COM_Outptr_ IKeyEnumerator** enumerator) PURE;
The key based forms of the APIs (including those used for key creation) are: 
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(EnumerateKeys)(_COM_Outptr_ IKeyEnumerator** enumerator) PURE;
STDMETHOD(ClearKeys)() PURE;

Ссылочные формы API:

STDMETHOD(GetKeyReference)(_In_ PCWSTR key, _COM_Errorptr_opt_ IModelObject** objectReference, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
STDMETHOD(EnumerateKeyReferences)(_COM_Outptr_ IKeyEnumerator** enumerator) PURE;

GetKeyValue

Метод GetKeyValue является первым методом, к которым клиент будет обращаться, чтобы получить значение (и метаданные, связанные с) заданным ключом по имени. Если ключ является методом доступа к свойствам, то это значение в качестве объекта IModelObject, который является прямоугольным методом IModelPropertyAccessor, метод GetKeyValue автоматически вызывает метод GetValue для получения фактического значения.

SetKeyValue

Метод SetKeyValue — это первый метод, на который клиент будет обращаться, чтобы задать значение ключа. Этот метод нельзя использовать для создания нового ключа объекта. Он задает только значение существующего ключа. Обратите внимание, что многие ключи доступны только для чтения (например, они реализуются методом доступа к свойствам, который возвращает E_NOT_IMPL из метода SetValue). Этот метод завершится ошибкой при вызове только ключа чтения.

ПеречислениеKeyValues

Метод EnumerateKeyValues — это первый метод, на который клиент будет обращаться, чтобы перечислить все ключи объекта (это включает все ключи, реализованные в любом месте дерева родительских моделей). Важно отметить, что EnumerateKeyValues перечисляет все ключи, определенные повторяющимися именами в дереве объектов; однако методы, такие как GetKeyValue и SetKeyValue, будут управлять только первым экземпляром ключа с заданным именем, как обнаружено глубиной первого обхода.

GetKey

Метод GetKey получит значение (и метаданные, связанные с) заданным ключом по имени. Вместо этого большинство клиентов должны использовать метод GetKeyValue. Если ключ является методом доступа к свойствам, вызывая этот метод, возвращает метод доступа к свойствам (интерфейс IModelPropertyAccessor) в IModelObject. В отличие от GetKeyValue, этот метод не будет автоматически разрешать базовое значение ключа путем вызова метода GetValue. Эта ответственность является вызывающим.

SetKey

Метод SetKey — это метод, на который клиент будет обращаться, чтобы создать ключ для объекта (и потенциально связать метаданные с созданным ключом). Если заданный объект уже имеет ключ с заданным именем, произойдет одно из двух действий. Если ключ находится в экземпляре, заданном этим, значение этого ключа будет заменено, как если бы исходный ключ не существовал. Если, с другой стороны, ключ находится в цепочке родительских моделей данных экземпляра, заданного этим, новый ключ с заданным именем будет создан на экземпляре, заданном этим. Это приведет к тому, что объект имеет два ключа одного и того же имени (аналогично производному классу, тенируя член того же имени, что и базовый класс).

ПеречислениеKeys

Метод EnumerateKeys работает аналогично методу EnumerateKeyValues, за исключением того, что он не разрешает метод доступа к свойствам в объекте автоматически. Это означает, что если значение ключа является методом доступа к свойствам, метод EnumerateKeys вернет метод доступа к свойствам (IModelPropertyAccessorInterface), размещенный в IModelObject, а не автоматически вызывая метод GetValue. Это похоже на разницу между GetKey и GetKeyValue.

ClearKeys

Метод ClearKeys удаляет все ключи и связанные с ними значения и метаданные из экземпляра объекта, указанного этим объектом. Этот метод не влияет на родительские модели, подключенные к конкретному экземпляру объекта.

GetKeyReference

Метод GetKeyReference будет искать ключ заданного имени объекта (или его родительской цепочки моделей) и возвращать ссылку на этот ключ, заданный интерфейсом IModelKeyReference в IModelObject. Эта ссылка впоследствии может использоваться для получения или задания значения ключа.

ПеречислениеKeyReferences

Метод EnumerateKeyReferences работает аналогично методу EnumerateKeyValues, за исключением того, что он возвращает ссылки на перечисленные ключи (с помощью интерфейса IModelKeyReference, прямоугольного в IModelObject) вместо значения ключа. Такие ссылки можно использовать для получения или задания базового значения ключей.

Методы обработки концепции

Помимо объекта модели, являющегося словарем кортежей ключей, значений и метаданных, он также является контейнером концепций. Понятие является абстрактным, которое может выполняться в объекте или в ней. Основные понятия, по сути, представляют собой динамическое хранилище интерфейсов, поддерживаемых объектом. Ряд концепций определяется моделью данных сегодня:

Интерфейс концепции Description
IDataModelConcept Концепция является родительской моделью. Если эта модель автоматически присоединяется к собственному типу через сигнатуру зарегистрированного типа, метод InitializeObject будет автоматически вызываться при каждом создании экземпляра нового объекта такого типа.
IStringDisplayableConcept Объект можно преобразовать в строку для отображения.
IIterableConcept Объект является контейнером и может быть итерирован.
IIndexableConcept Объект является контейнером и может быть индексирован (доступ через случайный доступ) в одном или нескольких измерениях.
IPreferredRuntimeTypeConcept Объект понимает больше о типах, производных от него, чем базовая система типов может предоставлять и обрабатывать собственные преобразования из статического в тип среды выполнения.
IDynamicKeyProviderConcept Объект является динамическим поставщиком ключей и хочет взять на себя все ключевые запросы из основной модели данных. Этот интерфейс обычно используется в качестве моста к динамическим языкам, таким как JavaScript.
IDynamicConceptProviderConcept Объект является динамическим поставщиком концепций и хочет взять на себя все основные запросы из основной модели данных. Этот интерфейс обычно используется в качестве моста к динамическим языкам, таким как JavaScript.

Для управления понятиями, поддерживаемыми объектом, используются следующие методы в IModelObject.

STDMETHOD(GetConcept)(_In_ REFIID conceptId, _COM_Outptr_ IUnknown** conceptInterface, _COM_Outptr_opt_result_maybenull_ IKeyStore** conceptMetadata) PURE;
STDMETHOD(SetConcept)(_In_ REFIID conceptId, _In_ IUnknown* conceptInterface, _In_opt_ IKeyStore* conceptMetadata) PURE;
STDMETHOD(ClearConcepts)() PURE;

GetConcept

Метод GetConcept будет искать концепцию объекта (или его родительской цепочки моделей) и возвращать указатель интерфейса на интерфейс концепции. Поведение и методы в интерфейсе концепции зависят от каждой концепции. Однако важно отметить, что многие из интерфейсов концепции требуют явного передачи объекта контекста (или того, что может традиционно вызывать этот указатель). Важно убедиться, что правильный объект контекста передается каждому интерфейсу концепции.

SetConcept

Метод SetConcept поместит указанную концепцию в экземпляр объекта, указанный этим указателем. Если родительская модель, присоединенная к экземпляру объекта, заданному этим, также поддерживает концепцию, реализация в экземпляре переопределит ее в родительской модели.

ClearConcepts

Метод ClearConcepts удаляет все понятия из экземпляра объекта, указанного этим объектом.

Методы собственных объектов

Хотя многие объекты модели относятся к встроенным (например, целым числам, строкам) или искусственным конструкциям (словарю кортежей и понятий "ключ-значение"/метаданные"), объект модели может также ссылаться на собственную конструкцию (например, определяемый пользователем тип в адресном пространстве целевого объекта отладки). В интерфейсе IModelObject есть ряд методов, к которым обращаются сведения о таких собственных объектах. Эти методы:

STDMETHOD(GetRawValue)(_In_ SymbolKind kind, _In_ PCWSTR name, _In_ ULONG searchFlags, _COM_Errorptr_ IModelObject** object) PURE;
STDMETHOD(EnumerateRawValues)(_In_ SymbolKind kind, _In_ ULONG searchFlags, _COM_Outptr_ IRawEnumerator** enumerator) PURE;
STDMETHOD(TryCastToRuntimeType)(_COM_Errorptr_ IModelObject** runtimeTypedObject) PURE;
STDMETHOD(GetLocation)(_Out_ Location* location) PURE;
STDMETHOD(GetTypeInfo)(_Out_ IDebugHostType** type) PURE;
STDMETHOD(GetTargetInfo)(_Out_ Location* location, _Out_ IDebugHostType** type) PURE;
STDMETHOD(GetRawReference)(_In_ SymbolKind kind, _In_ PCWSTR name, _In_ ULONG searchFlags, _COM_Errorptr_ IModelObject** object) PURE;
STDMETHOD(EnumerateRawReferences)(_In_ SymbolKind kind, _In_ ULONG searchFlags, _COM_Outptr_ IRawEnumerator** enumerator) PURE;

GetRawValue

Метод GetRawValue находит собственную конструкцию в заданном объекте. Такая конструкция может быть полем, базовым классом, полем базового класса, функцией-членом и т. д.

ПеречислениеRawValues

Метод EnumerateRawValues перечисляет все собственные дочерние элементы (например, поля, базовые классы и т. д.) данного объекта.

TryCastToRuntimeType

Метод TryCastToRuntimeType предложит узлу отладки выполнить анализ и определить фактический тип среды выполнения (например, большинство производных классов) данного объекта. Точный анализ, используемый для узла отладки, может включать RTTI (сведения о типе времени выполнения C++), изучение структуры виртуальной таблицы-таблицы функций объекта или любое другое означает, что узел может использовать для надежного определения типа динамической или среды выполнения из статического типа. Сбой преобразования в тип среды выполнения не означает, что этот вызов метода завершится ошибкой. В таких случаях метод вернет заданный объект (этот указатель) в выходном аргументе.

GetLocation

Метод GetLocation возвращает расположение собственного объекта. Хотя такое расположение обычно является виртуальным адресом в адресном пространстве целевого объекта отладки, это не обязательно так. Расположение, возвращаемое этим методом, является абстрактным расположением, которое может быть виртуальным адресом, может указывать размещение в регистре или вложенном регистре или может указывать на другое произвольное адресное пространство, определенное узлом отладки. Если поле HostDefined объекта результирующего объекта Location равно 0, оно указывает, что расположение фактически является виртуальным адресом. Такой виртуальный адрес можно получить, проверив поле "Смещение" результирующего расположения. Любое ненулевое значение поля HostDefined указывает альтернативное адресное пространство, в котором поле "Смещение" является смещением в этом адресном пространстве. Точное значение ненулевых значений HostDefined здесь является закрытым для узла отладки.

GetTypeInfo

Метод GetTypeInfo возвращает собственный тип данного объекта. Если объект не имеет сведений о собственном типе, связанных с ним (например, это встроенный объект и т. д.), вызов по-прежнему будет выполнен успешно, но вернет значение NULL.

GetTargetInfo

Метод GetTargetInfo фактически представляет собой сочетание методов GetLocation и GetTypeInfo, возвращающих абстрактное расположение, а также собственный тип данного объекта.

GetRawReference

Метод GetRawReference находит собственную конструкцию в заданном объекте и возвращает ссылку на нее. Такая конструкция может быть полем, базовым классом, полем базового класса, функцией-членом и т. д. Важно различать возвращаемую здесь ссылку (объект типа ObjectTargetObjectReference) от ссылки на язык (например, ссылку на C++ и &&&style).

ПеречислениеRawReferences

Метод EnumerateRawReferences перечисляет ссылки на все дочерние элементы собственного кода (например, поля, базовые классы и т. д.) данного объекта.

Методы расширяемости

Как описано ранее, объект модели работает очень похоже на объект JavaScript и его цепочку прототипов. Помимо экземпляра, представленного заданным интерфейсом IModelObject, может быть произвольное количество родительских моделей, присоединенных к объекту (каждое из которых, в свою очередь, может иметь произвольное число родительских моделей, присоединенных к ним). Это основное средство расширения в модели данных. Если заданное свойство или понятие не может находиться в данном экземпляре, выполняется поиск дерева объектов (определяемых родительскими моделями), корнями в экземпляре.

Следующие методы управляют цепочкой родительских моделей, связанных с заданным экземпляром IModelObject:

STDMETHOD(GetNumberOfParentModels)(_Out_ ULONG64* numModels) PURE;
STDMETHOD(GetParentModel)(_In_ ULONG64 i, _COM_Outptr_ IModelObject **model, _COM_Outptr_result_maybenull_ IModelObject **contextObject) PURE;
STDMETHOD(AddParentModel)(_In_ IModelObject* model, _In_opt_ IModelObject* contextObject, _In_ bool override) PURE;
STDMETHOD(RemoveParentModel)(_In_ IModelObject* model) PURE;
STDMETHOD(SetContextForDataModel)(_In_ IModelObject* dataModelObject, _In_ IUnknown* context) PURE;
STDMETHOD(GetContextForDataModel)(_In_ IModelObject* dataModelObject, _Out_ IUnknown** context) PURE;

GetNumberOfParentModels

Метод GetNumberOfParentModels возвращает количество родительских моделей, присоединенных к заданному экземпляру объекта. Родительские модели ищут глубину свойств в линейном порядке родительской цепочки моделей.

GetParentModel

Метод GetParentModel возвращает родительскую модель i-th в цепочке родительской модели заданного объекта. Родительские модели ищут свойство или концепцию в линейном порядке, которые они добавляются или перечисляются. Родительская модель с индексом i от нуля выполняется поиск (иерархически) до родительской модели с индексом i + 1.

AddParentModel

Метод AddParentModel добавляет новую родительскую модель в заданный объект. Такая модель может быть добавлена в конце цепочки поиска (аргумент переопределения указывается как false) или в передней части цепочки поиска (аргумент переопределения указывается как true). Кроме того, каждая родительская модель может дополнительно настроить контекст (семантику этого указателя) для любого свойства или концепции данного родительского (или любого пользователя в родительской иерархии). Корректировка контекста редко используется, но позволяет использовать некоторые мощные понятия, такие как внедрение объектов, создание пространств имен и т. д.

RemoveParentModel

RemoveParentModel удаляет указанную родительскую модель из родительской цепочки поиска заданного объекта.

SetContextForDataModel

Метод SetContextForDataModel используется реализацией модели данных для размещения данных данных на объектах экземпляров. Концептуально каждый IModelObject (вызывает этот экземпляр для простоты) содержит хэш-таблицу состояния. Хэш-таблица индексируется другой IModelObject (вызовите эту модель данных для простоты), которая находится в родительской иерархии модели экземпляра. Значение, содержащееся в этом хэше, — это набор ссылочных сведений о состоянии, представленных экземпляром IUnknown. После установки этого состояния в экземпляре модель данных может хранить данные произвольной реализации, которые можно получить во время таких действий, как получение свойств.

GetContextForDataModel

Метод GetContextForDataModel используется для получения сведений о контексте, настроенных с помощью предыдущего вызова SetContextForDataModel. При этом извлекаются сведения о состоянии, заданные в объекте экземпляра моделью данных, далее в иерархии родительской модели объекта экземпляра. Дополнительные сведения об этом контексте или состоянии и его значении см. в документации по SetContextForDataModel.

Основные типы объектов модели данных отладчика

Объект в модели данных похож на понятие Object в .NET. Это универсальный контейнер, в который создается конструкция, которую модель данных понимает, можно упаковать. Помимо собственных объектов и синтетических (динамических) объектов есть ряд основных типов объектов, которые можно поместить (или упаковать) в контейнер IModelObject. Контейнер, в котором большинство этих значений помещаются, является стандартным COM/OLE VARIANT с рядом дополнительных ограничений, которые могут содержать этот VARIANT. Ниже приведены основные типы следующих типов:

  • 8-разрядные и подписанные значения (VT_UI1, VT_I1)
  • 16-разрядные и подписанные значения (VT_UI2, VT_UI2)
  • 32-разрядные значения без знака и подписи (VT_UI4, VT_I4)
  • 64-разрядные и подписанные значения (VT_UI8, VT_I8)
  • Значения с плавающей запятой с одной и двойной точностью (VT_R4, VT_R8)
  • Строки (VT_BSTR)
  • Логические (VT_BOOL)

Помимо этих базовых типов, ряд основных объектов модели данных помещаются в IModelObject, определенный VT_UNKNOWN, где хранимый IUnknown гарантированно реализует конкретный интерфейс. Это следующие типы:

  • Методы доступа к свойствам (IModelPropertyAccessor)
  • Объекты метода (IModelMethod)
  • Ключевые эталонные объекты (IModelKeyReference или IModelKeyReference2)
  • Объекты контекста (IDebugModelHostContext)

Методы доступа к свойствам: IModelPropertyAccessor

Метод доступа к свойствам в модели данных — это реализация интерфейса IModelPropertyAccessor, который упаковается в IModelObject. Объект модели возвращает тип ObjectPropertyAccessor при запросе, а встроенное значение — это VT_UNKNOWN, который гарантированно будет запрашиваться для IModelPropertyAccessor. В процессе он гарантированно будет статически приведение к IModelPropertyAccessor.

Метод доступа к свойствам — это косвенный способ получения и задания ключевого значения в модели данных. Если значение заданного ключа является методом доступа к свойствам, методы GetKeyValue и SetKeyValue автоматически заметят это и вызовут базовые методы GetValue или SetValue в качестве соответствующего метода доступа к свойству.

Интерфейс IModelPropertyAccessor определяется следующим образом:

DECLARE_INTERFACE_(IModelPropertyAccessor, IUnknown)
{
    STDMETHOD(GetValue)(_In_ PCWSTR key, _In_opt_ IModelObject* contextObject, _COM_Outptr_ IModelObject** value) PURE;
    STDMETHOD(SetValue)(_In_ PCWSTR key, _In_opt_ IModelObject* contextObject, _In_ IModelObject* value) PURE; 
}

GetValue

Метод GetValue — это метод получения для метода доступа к свойствам. Он вызывается всякий раз, когда клиент хочет получить базовое значение свойства. Обратите внимание, что любой вызывающий объект, который непосредственно получает метод доступа к свойству, отвечает за передачу имени ключа и точного объекта экземпляра (этот указатель) методу GetValue метода доступа к свойству.

SetValue

Метод SetValue — это метод задания для метода доступа к свойствам. Он вызывается всякий раз, когда клиент хочет назначить значение базовому свойству. Многие свойства доступны только для чтения. В таких случаях вызов метода SetValue вернет E_NOTIMPL. Обратите внимание, что любой вызывающий объект, который непосредственно получает метод доступа к свойству, отвечает за передачу имени ключа и точного объекта экземпляра (этот указатель) методу SetValue средства доступа к свойству.

Методы: IModelMethod

Метод в модели данных — это реализация интерфейса IModelMethod, который упаковается в IModelObject. Объект модели возвращает тип ObjectMethod при запросе, а встроенное значение — это VT_UNKNOWN, который гарантированно будет запрашиваться для IModelMethod. В процессе он гарантированно будет статически приведение к IModelMethod. Все методы в модели данных являются динамическими в природе. Они принимают в качестве входных данных набор 0 или более аргументов и возвращают одно выходное значение. Разрешения перегрузки отсутствуют и метаданные о именах параметров, типах или ожиданиях.

Интерфейс IModelMethod определяется следующим образом:

DECLARE_INTERFACE_(IModelMethod, IUnknown)
{
    STDMETHOD(Call)(_In_opt_ IModelObject *pContextObject, _In_ ULONG64 argCount, _In_reads_(argCount) IModelObject **ppArguments, _COM_Errorptr_ IModelObject **ppResult, _COM_Outptr_opt_result_maybenull_ IKeyStore **ppMetadata) PURE;
}

Call

Метод Call — это способ вызова любого метода, определенного в модели данных. Вызывающий объект отвечает за передачу точного объекта экземпляра (этот указатель) и произвольного набора аргументов. Возвращается результат метода и любые необязательные метаданные, связанные с этим результатом. Методы, которые логически не возвращают значение, по-прежнему должны возвращать допустимый объект IModelObject. В таком случае IModelObject не является полем. В случае сбоя метода может возвращать необязательные расширенные сведения об ошибке в входном аргументе (даже если возвращенный HRESULT является сбоем). Настоятельно необходимо, чтобы вызывающие проверка для этого.

Ключевые ссылки: IModelKeyReference или IModelKeyReference2

По сути, ключевой ссылкой является дескриптор ключа для определенного объекта. Клиент может получить такой дескриптор с помощью таких методов, как GetKeyReference, и использовать дескриптор позже, чтобы получить или задать значение ключа без обязательного удержания исходного объекта. Этот тип объекта является реализацией интерфейса IModelKeyReference или IModelKeyReference2, который упаковается в IModelObject. Объект модели возвращает тип ObjectKeyReference при запросе, а затем встроенное значение является VT_UNKNOWN, который гарантированно будет запрашиваться для IModelKeyReference. В процессе он гарантированно будет статически приведение к IModelKeyReference.

Ключевой эталонный интерфейс определяется следующим образом:

DECLARE_INTERFACE_(IModelKeyReference2, IModelKeyReference)
{
    STDMETHOD(GetKeyName)(_Out_ BSTR* keyName) PURE;
    STDMETHOD(GetOriginalObject)(_COM_Outptr_ IModelObject** originalObject) PURE;
    STDMETHOD(GetContextObject)(_COM_Outptr_ IModelObject** containingObject) PURE;
    STDMETHOD(GetKey)(_COM_Errorptr_opt_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
    STDMETHOD(GetKeyValue)(_COM_Errorptr_opt_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
    STDMETHOD(SetKey)(_In_opt_ IModelObject* object, _In_opt_ IKeyStore* metadata) PURE;
    STDMETHOD(SetKeyValue)(_In_ IModelObject* object) PURE;
    STDMETHOD(OverrideContextObject)(_In_ IModelObject* newContextObject) PURE;
}

GetKeyName

Метод GetKeyName возвращает имя ключа, к которому ссылается этот ключ, является дескриптором. Возвращаемая строка является стандартной BSTR и должна быть освобождена с помощью вызова SysFreeString.

GetOriginalObject

Метод GetOriginalObject возвращает объект экземпляра, из которого была создана ссылка на ключ. Обратите внимание, что ключ может находиться в родительской модели объекта экземпляра.

GetContextObject

Метод GetContextObject возвращает контекст (этот указатель), который будет передан методу GetValue или SetValue объекта доступа свойств, если ключ, заданный в вопросе, относится к методу доступа к свойствам. Возвращаемый здесь объект контекста может совпадать с исходным объектом, полученным из GetOriginalObject. Если ключ находится в родительской модели и существует адаптатор контекста, связанный с этой родительской моделью, исходный объект является объектом экземпляра, на котором был вызван GetKeyReference или EnumerateKeyReferences. Объект контекста будет тем, что выходит из конечного адаптатора контекста между исходным объектом и родительской моделью, содержащей ключ, к которому ссылается этот ключ, является дескриптором. Если нет адаптаторов контекста, исходный объект и объект контекста идентичны.

GetKey

Метод GetKey в ссылке на ключ ведет себя как метод GetKey в IModelObject. Он возвращает значение базового ключа и все метаданные, связанные с ключом. Если значение ключа будет методом доступа к свойствам, он вернет объект доступа к свойствам (IModelPropertyAccessor) в IModelObject. Этот метод не вызывает базовые методы GetValue или SetValue в методе доступа к свойствам.

GetKeyValue

Метод GetKeyValue в ссылке на ключ ведет себя как метод GetKeyValue в IModelObject. Он возвращает значение базового ключа и все метаданные, связанные с ключом. Если значение ключа будет методом доступа к свойствам, это вызовет базовый метод GetValue в методе доступа к свойствам автоматически.

SetKey

Метод SetKey в ссылке на ключ ведет себя как метод SetKey в IModelObject. Присвойте ему значение ключа. Если исходный ключ был методом доступа к свойствам, он заменит метод доступа к свойствам. Метод SetValue не вызывается в методе доступа к свойствам.

SetKeyValue

Метод SetKeyValue в ссылке на ключ ведет себя как метод SetKeyValue в IModelObject. Присвойте ему значение ключа. Если исходный ключ был методом доступа к свойствам, он вызовет базовый метод SetValue в методе доступа к свойствам, а не заменяет сам метод доступа к свойствам.

OverrideContextObject

Метод OverrideContextObject (только в IModelKeyReference2) — это расширенный метод, который используется для постоянного изменения объекта контекста, который будет передаваться любому базовому методу доступа к свойствам GetValue или SetValue. Объект, переданный этому методу, также будет возвращен из вызова GetContextObject. Этот метод можно использовать поставщиками скриптов для реплика параметров определенного динамического языка. Большинство клиентов не должны вызывать этот метод.

Объекты контекста: IDebugHostContext

Объекты контекста — это непрозрачные большие двоичные объекты информации, которые узел отладки (в сотрудничестве с моделью данных) связывается с каждым объектом. Это может включать такие вещи, как контекст процесса или адресное пространство, из которых поступает информация и т. д. Объект контекста — это реализация IDebugHostContext в IModelObject. Обратите внимание, что IDebugHostContext — это определенный узлом интерфейс. Клиент никогда не реализует этот интерфейс.

Дополнительные сведения о объектах контекста см. в разделе Интерфейсы узла модели данных C++ отладчика в интерфейсах C++ модели данных отладчика.

Диспетчер моделей данных

Основной интерфейс диспетчера моделей данных IDataModelManager2 (или более ранний IDataModelManager) определяется следующим образом:

DECLARE_INTERFACE_(IDataModelManager2, IDataModelManager)
{
    //
    // IDataModelManager:
    //
    STDMETHOD(Close)() PURE;
    STDMETHOD(CreateNoValue)(_Out_ IModelObject** object) PURE;
    STDMETHOD(CreateErrorObject)(_In_ HRESULT hrError, _In_opt_ PCWSTR pwszMessage, _COM_Outptr_ IModelObject** object) PURE;
    STDMETHOD(CreateTypedObject)(_In_opt_ IDebugHostContext* context, _In_ Location objectLocation, _In_ IDebugHostType* objectType, _COM_Errorptr_ IModelObject** object) PURE;
    STDMETHOD(CreateTypedObjectReference)(_In_opt_ IDebugHostContext* context, _In_ Location objectLocation, _In_ IDebugHostType* objectType, _COM_Errorptr_ IModelObject** object) PURE;
    STDMETHOD(CreateSyntheticObject)(_In_opt_ IDebugHostContext* context, _COM_Outptr_ IModelObject** object) PURE;
    STDMETHOD(CreateDataModelObject)(_In_ IDataModelConcept* dataModel, _COM_Outptr_ IModelObject** object) PURE;
    STDMETHOD(CreateIntrinsicObject)(_In_ ModelObjectKind objectKind, _In_ VARIANT* intrinsicData, _COM_Outptr_ IModelObject** object) PURE;
    STDMETHOD(CreateTypedIntrinsicObject)(_In_ VARIANT* intrinsicData, _In_ IDebugHostType* type, _COM_Outptr_ IModelObject** object) PURE;
    STDMETHOD(GetModelForTypeSignature)(_In_ IDebugHostTypeSignature* typeSignature, _Out_ IModelObject** dataModel) PURE;
    STDMETHOD(GetModelForType)(_In_ IDebugHostType* type, _COM_Outptr_ IModelObject** dataModel, _COM_Outptr_opt_ IDebugHostTypeSignature** typeSignature, _COM_Outptr_opt_ IDebugHostSymbolEnumerator** wildcardMatches) PURE;
    STDMETHOD(RegisterModelForTypeSignature)(_In_ IDebugHostTypeSignature* typeSignature, _In_ IModelObject* dataModel) PURE;
    STDMETHOD(UnregisterModelForTypeSignature)(_In_ IModelObject* dataModel, _In_opt_ IDebugHostTypeSignature* typeSignature) PURE;
    STDMETHOD(RegisterExtensionForTypeSignature)(_In_ IDebugHostTypeSignature* typeSignature, _In_ IModelObject* dataModel) PURE;
    STDMETHOD(UnregisterExtensionForTypeSignature)(_In_ IModelObject* dataModel, _In_opt_ IDebugHostTypeSignature* typeSignature) PURE;
    STDMETHOD(CreateMetadataStore)(_In_opt_ IKeyStore* parentStore, _COM_Outptr_ IKeyStore** metadataStore) PURE;
    STDMETHOD(GetRootNamespace)(_COM_Outptr_ IModelObject** rootNamespace) PURE;
    STDMETHOD(RegisterNamedModel)(_In_ PCWSTR modelName, _In_ IModelObject *modeObject) PURE;
    STDMETHOD(UnregisterNamedModel)(_In_ PCWSTR modelName) PURE;
    STDMETHOD(AcquireNamedModel)(_In_ PCWSTR modelName, _COM_Outptr_ IModelObject **modelObject) PURE;
    //
    // IDataModelManager2:
    //
    STDMETHOD(AcquireSubNamespace)(_In_ PCWSTR modelName, _In_ PCWSTR subNamespaceModelName, _In_ PCWSTR accessName, _In_opt_ IKeyStore *metadata, _COM_Outptr_ IModelObject **namespaceModelObject) PURE;
    STDMETHOD(CreateTypedIntrinsicObjectEx)(_In_opt_ IDebugHostContext* context, _In_ VARIANT* intrinsicData, _In_ IDebugHostType* type, _COM_Outptr_ IModelObject** object) PURE;
}

Методы управления

Следующий набор методов используется приложением (например, отладчиком), на котором размещена модель данных.

STDMETHOD(Close)() PURE;

Закрыть

Метод Close вызывается в диспетчере моделей данных приложением (например, отладчиком), в котором размещается модель данных, чтобы запустить процесс завершения работы диспетчера моделей данных. Узел модели данных, которая не является методом Close до выпуска окончательной ссылки на диспетчер моделей данных, может привести к неопределенному поведению, включая, но не ограничивается, значительными утечками инфраструктуры управления для модели данных.

Методы создания объектов и бокса

Следующий набор методов используется для создания новых объектов или поля значений в IModelObject — основной интерфейс модели данных.

STDMETHOD(CreateNoValue)(_Out_ IModelObject** object) PURE;
STDMETHOD(CreateErrorObject)(_In_ HRESULT hrError, _In_opt_ PCWSTR pwszMessage, _COM_Outptr_ IModelObject** object) PURE;
STDMETHOD(CreateTypedObject)(_In_opt_ IDebugHostContext* context, _In_ Location objectLocation, _In_ IDebugHostType* objectType, _COM_Errorptr_ IModelObject** object) PURE;
STDMETHOD(CreateTypedObjectReference)(_In_opt_ IDebugHostContext* context, _In_ Location objectLocation, _In_ IDebugHostType* objectType, _COM_Errorptr_ IModelObject** object) PURE;
STDMETHOD(CreateSyntheticObject)(_In_opt_ IDebugHostContext* context, _COM_Outptr_ IModelObject** object) PURE;
STDMETHOD(CreateDataModelObject)(_In_ IDataModelConcept* dataModel, _COM_Outptr_ IModelObject** object) PURE;
STDMETHOD(CreateIntrinsicObject)(_In_ ModelObjectKind objectKind, _In_ VARIANT* intrinsicData, _COM_Outptr_ IModelObject** object) PURE;
STDMETHOD(CreateTypedIntrinsicObject)(_In_ VARIANT* intrinsicData, _In_ IDebugHostType* type, _COM_Outptr_ IModelObject** object) PURE;
STDMETHOD(CreateMetadataStore)(_In_opt_ IKeyStore* parentStore, _COM_Outptr_ IKeyStore** metadataStore) PURE;
STDMETHOD(CreateTypedIntrinsicObjectEx)(_In_opt_ IDebugHostContext* context, _In_ VARIANT* intrinsicData, _In_ IDebugHostType* type, _COM_Outptr_ IModelObject** object) PURE;

CreateNoValue

Метод CreateNoValue создает объект "без значения", упаковывает его в объект IModelObject и возвращает его. Возвращаемый объект модели имеет тип ObjectNoValue.

Объект "без значения" имеет несколько семантических значений:

  • (В зависимости от языка) его можно рассматривать как семантический эквивалент void, null или неопределенный
  • Метод GetValue любого метода доступа к свойствам, который возвращает успех и результирующий объект "нет значения" указывает, что конкретное свойство не имеет значения для данного экземпляра и должно рассматриваться как если бы свойство не существовало для этого конкретного экземпляра.
  • Методы модели данных, не имеющие семантически возвращаемого значения, используются в качестве sentinel для указания такого типа (например, метод должен возвращать допустимый объект IModelObject).

CreateErrorObject

Метод CreateErrorObject создает объект error. Модель данных не имеет понятия об исключениях и потоке исключений. Сбой выходит из свойства или метода двумя способами:

  • Один сбой HRESULT без расширенных сведений об ошибке. Либо нет дополнительных сведений, которые можно указать для ошибки, либо сама ошибка является самообъяснительной из возвращаемого HRESULT.
  • Один сбой HRESULT, в сочетании с расширенными сведениями об ошибке. Расширенные сведения об ошибке — это объект ошибки, возвращаемый в выходном аргументе свойства или метода.

CreateTypedObject

Метод CreateTypedObject — это метод, который позволяет клиенту создавать представление объекта машинного или языкового языка в адресном пространстве целевого объекта отладки. Если тип только что созданного объекта (как указано аргументом objectType) соответствует одному или нескольким подписям типов, зарегистрированным в диспетчере моделей данных как канонические визуализаторы или расширения, эти соответствующие модели данных автоматически будут присоединены к объекту созданного экземпляра перед возвратом вызывающему объекту.

CreateTypedObjectReference

Метод CreateTypedObjectReference семантической аналогичен методу CreateTypedObject, за исключением того, что он создает ссылку на базовую конструкцию собственного языка или языка. Созданная ссылка — это объект, имеющий вид ObjectTargetObjectReference. Это не собственная ссылка, так как базовый язык может поддерживать (например, C++ и&>). Объект ObjectTargetObjectReference можно получить в ссылке на C++. Объект типа ObjectTargetObjectReference можно преобразовать в базовое значение с помощью метода Dereference в IModelObject. Ссылку также можно передать базовому вычислителю выражений узла, чтобы присвоить значение соответствующему языку.

CreateSyntheticObject

Метод CreateSyntheticObject создает пустой объект модели данных — словарь кортежей и понятий key/value/metadata. Во время создания ключи и понятия для объекта отсутствуют. Это чистый лист для вызывающего абонента, который будет использовать.

CreateDataModelObject

Метод CreateDataModelObject — это простая вспомогательный оболочка для создания объектов, которые являются моделями данных. Это объекты, которые будут присоединены как родительские модели к другим объектам. Все такие объекты должны поддерживать концепцию модели данных с помощью IDataModelConcept. Этот метод создает пустой искусственный объект без явного контекста и добавляет входной объект IDataModelConcept в качестве реализации созданного объекта концепции модели данных. Это можно сделать аналогично с помощью вызовов CreateSyntheticObject и SetConcept.

CreateIntrinsicObject

Метод CreateIntrinsicObject — это метод, который упаковывает встроенные значения в IModelObject. Вызывающий объект помещает значение в COM VARIANT и вызывает этот метод. Диспетчер моделей данных возвращает объект IModelObject, представляющий объект. Обратите внимание, что этот метод также используется для поля основных типов на основе IUnknown: методы доступа к свойствам, методы, контексты и т. д. В таких случаях метод objectKind указывает, какой вид конструкции на основе IUnknown представляет объект, а поле punkVal переданного варианта является производным типом IUnknown. Тип должен быть статически приведение к соответствующему интерфейсу модели (например, IModelPropertyAccessor, IModelMethod, IDebugHostContext и т. д.) в процессе. Типы VARIANT, поддерживаемые этим методом, являются VT_UI1, VT_I1, VT_UI2, VT_I2, VT_UI4, VT_I4, VT_UI8, VT_I8, VT_R4, VT_R8, VT_BOOL, VT_BSTR и VT_UNKNOWN (для специализированного набора производных типов IUnknown, как указано в перечислении ModelObjectKind.

CreateTypedIntrinsicObject

Метод CreateTypedintrinsicObject аналогичен методу CreateIntrinsicObject, за исключением того, что он позволяет связать собственный или языковой тип с данными и перенести вместе с полем. Это позволяет модели данных представлять такие конструкции, как собственные типы перечисления (которые просто VT_UI* или VT_I*). Типы указателей также создаются с помощью этого метода. Собственный указатель в модели данных — это нулевая 64-разрядная величина, представляющая смещение в виртуальное адресное пространство целевого объекта отладки. Он находится в VT_UI8 и создается с помощью этого метода и типа, который указывает указатель на машинный или языковой код.

CreateMetadataStore

Метод CreateMetadataStore создает хранилище ключей — упрощенный контейнер кортежей ключей, значений или метаданных, который используется для хранения метаданных, которые могут быть связаны со свойствами и различными другими значениями. Хранилище метаданных может иметь один родительский элемент (который, в свою очередь, может иметь один родительский элемент). Если заданный ключ метаданных не расположен в данном хранилище, его родители проверка. Большинство хранилищ метаданных не имеют родителей. Однако это позволяет легко предоставлять общий доступ к общим метаданным.

CreateTypedIntrinsicObjectEx

Метод CreateTypedIntrinsicObjectEx семантической аналогичен методу CreateTypedIntrinsicObject. Единственное различие между этими двумя заключается в том, что этот метод позволяет вызывающему объекту указать контекст, в котором допустимы внутренние данные. Если контекст не передается, данные считаются допустимыми в любом контексте, унаследованным от аргумента типа (поведение CreateTypedIntrinsicObject). Это позволяет создавать типизированные значения указателя в целевом объекте отладки, для которого требуется более конкретный контекст, чем можно наследовать от типа.

Расширяемость / Методы регистрации: следующий набор методов управляет механизмом расширяемости модели данных, позволяя клиенту расширять или регистрировать существующие модели или запрашивать модель данных автоматически присоединять определенную родительскую модель к собственным типам, которые соответствуют заданному критерию.

    STDMETHOD(GetModelForTypeSignature)(_In_ IDebugHostTypeSignature* typeSignature, _Out_ IModelObject** dataModel) PURE;
    STDMETHOD(GetModelForType)(_In_ IDebugHostType* type, _COM_Outptr_ IModelObject** dataModel, _COM_Outptr_opt_ IDebugHostTypeSignature** typeSignature, _COM_Outptr_opt_ IDebugHostSymbolEnumerator** wildcardMatches) PURE;
    STDMETHOD(RegisterModelForTypeSignature)(_In_ IDebugHostTypeSignature* typeSignature, _In_ IModelObject* dataModel) PURE;
    STDMETHOD(UnregisterModelForTypeSignature)(_In_ IModelObject* dataModel, _In_opt_ IDebugHostTypeSignature* typeSignature) PURE;
    STDMETHOD(RegisterExtensionForTypeSignature)(_In_ IDebugHostTypeSignature* typeSignature, _In_ IModelObject* dataModel) PURE;
    STDMETHOD(UnregisterExtensionForTypeSignature)(_In_ IModelObject* dataModel, _In_opt_ IDebugHostTypeSignature* typeSignature) PURE;
    STDMETHOD(GetRootNamespace)(_COM_Outptr_ IModelObject** rootNamespace) PURE;
    STDMETHOD(RegisterNamedModel)(_In_ PCWSTR modelName, _In_ IModelObject *modeObject) PURE;
    STDMETHOD(UnregisterNamedModel)(_In_ PCWSTR modelName) PURE;
    STDMETHOD(AcquireNamedModel)(_In_ PCWSTR modelName, _COM_Outptr_ IModelObject **modelObject) PURE;

GetModelForTypeSignature

Метод GetModelForTypeSignature возвращает модель данных, зарегистрированную для определенной сигнатуры типа с помощью предыдущего вызова метода RegisterModelForTypeSignature. Модель данных, возвращаемая этим методом, считается каноническим визуализатором для любого типа, который соответствует сигнатуре переданного типа. Как канонический визуализатор, эта модель данных берет на себя отображение типа. Обработчики отображения по умолчанию скрывают конструкции собственного или языкового объекта в пользу представления объекта, представленного моделью данных.

GetModelForType

Метод GetModelForType возвращает модель данных, которая является каноническим визуализатором для данного экземпляра типа. В действительности этот метод находит лучшую сигнатуру типа, которая была зарегистрирована при предыдущем вызове метода RegisterModelForTypeSignature и возвращает связанную модель данных.

RegisterModelForTypeSignature

Метод RegisterModelForTypeSignature является основным методом, который вызывающий метод использует для регистрации канонического визуализатора для заданного типа (или набора типов). Канонический визуализатор — это модель данных, которая, в действительности, берет на себя отображение заданного типа (или набора типов). Вместо представления собственного или языкового представления типа, отображаемого в любом пользовательском интерфейсе отладчика, отображается представление типа, представленного зарегистрированной моделью данных (вместе с средством возврата к представлению собственного языка для пользователя, который хочет его).

Отмена регистрацииModelForTypeSignature

Метод UnregisterModelForTypeSignature отменяет предыдущий вызов метода RegisterModelForTypeSignature. Этот метод может либо удалить определенную модель данных в качестве канонического визуализатора для типов, соответствующих определенной сигнатуре типа, либо удалить определенную модель данных в качестве канонического визуализатора для каждой подписи типа, под которой зарегистрирована эта модель данных.

RegisterExtensionForTypeSignature

Метод RegisterExtensionForTypeSignature аналогичен методу RegisterModelForTypeSignature с одним ключевым различием. Модель данных, передаваемая этому методу, не является каноническим визуализатором для любого типа, и она не будет принимать на себя отображение представления собственного или языкового представления этого типа. Модель данных, передаваемая этому методу, автоматически добавляется в качестве родительского элемента в любой конкретный тип, соответствующий предоставленной сигнатуре типа. В отличие от метода RegisterModelForTypeSignature, нет ограничений на идентичные или неоднозначные подписи типов, зарегистрированные в качестве расширений для заданного типа (или набора типов). Каждое расширение, сигнатура которого соответствует заданному экземпляру конкретного типа, приведет к автоматическому присоединению модели данных, зарегистрированной с помощью этого метода, к вновь созданным объектам в качестве родительских моделей. Это позволяет произвольному количеству клиентов расширить тип (или набор типов) с новыми полями или функциями.

Отмена регистрацииExtensionForTypeSignature

Метод UnregisterExtensionForTypeSignature отменяет предыдущий вызов RegisterExtensionForTypeSignature. Она отменяет регистрацию конкретной модели данных в качестве расширения для определенной подписи типа или расширения для всех подписей типов, для которых была зарегистрирована модель данных.

GetRootNamespace

Метод GetRootNamespace возвращает корневое пространство имен модели данных. Это объект, которым управляет модель данных, и в которую узел отладки помещает определенные объекты.

RegisterNamedModel

Метод RegisterNamedModel регистрирует определенную модель данных под известным именем, чтобы ее могли найти клиенты, желающие расширить ее. Это основная цель API — опубликовать модель данных как то, что может быть расширено путем получения модели, зарегистрированной под этим хорошо известным именем, и добавления родительской модели в нее.

Отмена регистрацииNamedModel

Метод UnregisterNamedModel отменяет предыдущий вызов RegisterNamedModel. Он удаляет связь между моделью данных и именем, под которым его можно найти.

AcquireNamedModel

Вызывающий объект, который хочет расширить модель данных, зарегистрированную под заданным именем, вызывает метод AcquireNamedModel, чтобы получить объект для модели данных, которую они хотят расширить. Этот метод вернет любую модель данных, зарегистрированную перед вызовом метода RegisterNamedModel. В качестве основной цели метода AcquireNamedModel является расширение модели, этот метод имеет особое поведение, если модель еще не зарегистрирована под заданным именем. Если модель еще не зарегистрирована под заданным именем, создается объект заглушки, временно зарегистрированный под заданным именем и возвращен вызывающий объект. При регистрации реальной модели данных с помощью вызова метода RegisterNamedModel все изменения, внесенные в объект заглушки, в действительности вносятся в реальную модель. Это удаляет множество проблем с зависимостью порядка нагрузки от компонентов, которые расширяют друг друга.

Вспомогательные методы

Ниже приведены вспомогательные методы, помогающие выполнять сложные операции с объектами в модели данных. Хотя эти действия можно выполнить с помощью других методов в модели данных или его объектах, эти удобные методы значительно упрощают:

STDMETHOD(AcquireSubNamespace)(_In_ PCWSTR modelName, _In_ PCWSTR subNamespaceModelName, _In_ PCWSTR accessName, _In_opt_ IKeyStore *metadata, _COM_Outptr_ IModelObject **namespaceModelObject) PURE;

AcquireSubNamespace

Метод AcquireSubNamespace помогает в создании чего-то, что может более традиционно выглядеть как пространство имен языка, чем новый объект в динамическом языке. Например, если вызывающий объект хочет классифицировать свойства в объекте процесса, чтобы сделать объект процесса более упорядоченным, а свойства проще обнаруживать, один из способов этого — создать вложенный объект для каждой категории объекта процесса и поместить эти свойства внутри этого объекта.

См. также

Этот раздел является частью серии, в которой описываются интерфейсы, доступные на C++, как использовать их для создания расширения отладчика на основе C++ и использования других конструкций модели данных (например, JavaScript или NatVis) из расширения модели данных C++.

Обзор модели данных отладчика C++

Интерфейсы C++ модели данных отладчика

Дополнительные интерфейсы модели данных отладчика C++

Основные понятия модели данных C++ отладчика

Скрипты модели данных отладчика C++