Compartilhar via


Objetos do Modelo de Dados do Depurador C++

Este tópico descreve como usar objetos C++ do Modelo de Dados do Depurador e como eles podem estender os recursos do depurador.

o modelo de objeto do depurador principal

Uma das coisas mais básicas e poderosas sobre o modelo de dados é que ele padroniza a definição do que é um objeto e como ele interage com um objeto. A interface IModelObject encapsula a noção de um objeto, seja esse objeto um inteiro, um valor de ponto flutuante, uma cadeia de caracteres, algum tipo complexo no espaço de endereço de destino do depurador ou algum conceito de depurador, como a noção de um processo ou um módulo.

Há várias coisas diferentes que podem ser mantidas em um IModelObject:

  • valores intrínsecos – um IModelObject pode ser um contêiner para vários tipos básicos: 8, 16, 32 ou 64 bits com sinal ou inteiros sem sinal, booleanos, cadeias de caracteres, erros ou a noção de vazio.

  • objetos nativos - um IModelObject pode representar um tipo complexo (conforme definido pelo sistema de tipos do depurador) dentro do espaço de endereço de qualquer que seja o destino do depurador

  • objetos sintéticos – um IModelObject pode ser um objeto dinâmico – um dicionário, se desejar: uma coleção de tuplas chave/valor/metadados e um conjunto de conceitos que definem comportamentos que não são simplesmente representados por pares chave/valor.

  • Properties – um IModelObject pode representar uma propriedade: algo cujo valor pode ser recuperado ou alterado com uma chamada de método. Uma propriedade dentro de um IModelObject é efetivamente uma interface IModelPropertyAccessor boxed em um IModelObject

  • métodos – um IModelObject pode representar um método: algo que você pode chamar com um conjunto de argumentos e obter um valor retornado. Um método dentro de um IModelObject é efetivamente uma interface de IModelMethod em uma IModelObject

Extensibilidade dentro do modelo de objeto

Um IModelObject não é um objeto isolado. Além de representar um dos tipos de objetos mostrados acima, cada objeto tem a noção de uma cadeia de modelos de dados pai. Essa cadeia se comporta muito como uma cadeia de protótipos JavaScript. Em vez de uma cadeia linear de protótipos como o JavaScript, cada objeto de modelo de dados define uma cadeia linear de modelos pai. Cada um desses modelos pai, por sua vez, tem outra cadeia linear de seu próprio conjunto de pais. Em essência, cada objeto é uma agregação dos recursos (propriedades etc...) de si mesmo e de cada objeto nesta árvore. Quando uma propriedade específica é consultada, se o objeto em que ele é consultado não dá suporte a essa propriedade, a consulta é passada em ordem linear para cada pai, por sua vez. Isso cria um comportamento em que a pesquisa por uma propriedade é resolvida por uma pesquisa detalhada da árvore de agregação.

A extensibilidade dentro desse modelo de objeto é muito simples, considerando essa noção de que cada objeto é uma agregação de si mesmo e da árvore dos modelos pai. Uma extensão pode entrar e se adicionar à lista de modelos pai de outro objeto. Fazer esse estende o objeto. Dessa maneira, é possível adicionar funcionalidades a qualquer coisa: uma instância específica de um objeto ou valor, um tipo nativo, o conceito do depurador do que é um processo ou thread ou até mesmo a noção de "todos os objetos iteráveis".

Contexto, contexto e contexto: o esse ponteiro, o espaço de endereço e os dados privados de implementação

Há três noções de contexto que são necessárias para entender dentro do contexto do modelo de objeto.

Contexto: o este ponteiro de

Como uma determinada propriedade ou método pode ser implementado em qualquer nível da árvore de modelo de dados, é necessário que a implementação do método ou propriedade possa acessar o objeto original (o que você pode chamar de esse ponteiro em C++ ou o este objeto em JavaScript. Esse objeto de instância é passado para uma variedade de métodos como o primeiro argumento chamado contexto nos métodos descritos.

Contexto: o espaço de endereço

É importante observar que, ao contrário de modelos de extensão anteriores em que contexto (o destino, o processo, o thread que você está examinando) é um conceito de interface do usuário com todas as APIs relativas ao estado atual da interface do usuário, as interfaces de modelo de dados normalmente assumem esse contexto explicitamente ou implicitamente como uma interface de IDebugHostContext. Cada IModelObject dentro do modelo de dados carrega esse tipo de informação de contexto junto com ele e pode propagar esse contexto para objetos retornados por ele. Isso significa que, quando você lê um valor nativo ou um valor de chave de um IModelObject, ele será lido fora do destino e do processo do qual o objeto foi originalmente adquirido.

Há um valor constante explícito, USE_CURRENT_HOST_CONTEXT, que pode ser passado para métodos que levam um argumento IDebugHostContext. Esse valor indica que o contexto deve ser, de fato, o estado atual da interface do usuário do depurador. No entanto, essa noção precisa ser explícita.

Contexto: Implementação de dados privados

Lembre-se de que cada objeto no modelo de dados é, na verdade, uma agregação da instância de objeto e da árvore de modelos pai que estão anexados. Cada um desses modelos pai (que podem ser vinculados nas cadeias de muitos objetos diferentes) pode associar dados de implementação privados a qualquer objeto de instância. Cada IModelObject que é criado conceitualmente tem uma tabela de hash que mapeia de um modelo pai específico para dados de instância privada definidos por uma interface IUnknown. Isso permite que um modelo pai armazene informações em cache em todas as instâncias ou tenha dados arbitrários associados.

Esse tipo de contexto é acessado por meio dos métodos GetContextForDataModel e SetContextForDataModel em IModelObject.

a interface de objeto do depurador principal: IModelObject


A interface IModelObject é definida da seguinte maneira:

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;
}

métodos básicos

Veja a seguir os métodos gerais aplicáveis a qualquer tipo de objeto representado por um 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

O método GetKind retorna que tipo de objeto está em caixa dentro do IModelObject.

GetContext

O método GetContext retorna o contexto de host associado ao objeto.

GetIntrinsicValue

O método GetIntrinsicValue retorna a coisa que está em caixa dentro de um IModelObject. Esse método só pode ser chamado legalmente em interfaces IModelObject que representam um intrínseco em caixa ou uma interface específica que está em caixa. Ele não pode ser chamado em objetos nativos, nenhum objeto de valor, objetos sintéticos e objetos de referência. O método GetIntrinsicValueAs se comporta tanto quanto o método GetIntrinsicValue, exceto pelo fato de converter o valor no tipo de variante especificado. Se a conversão não puder ser executada, o método retornará um erro.

IsEqualTo

O método IsEqualTo compara dois objetos de modelo e retorna se eles são iguais em valor. Para o objeto que tem uma ordenação, esse método que retorna true é equivalente ao método Compare retornando 0. Para objetos que não têm ordenação, mas são equatable, o método Compare falhará, mas isso não ocorrerá. O significado de uma comparação baseada em valor é definido pelo tipo de objeto. No momento, isso só é definido para tipos intrínsecos e objetos de erro. Não há nenhum conceito de modelo de dados atual para equabilidade.

de desreferência

O método Dereference desreferencia um objeto. Esse método pode ser usado para desreferenciar uma referência baseada em modelo de dados (ObjectTargetObjectReference, ObjectKeyReference) ou uma referência de idioma nativo (um ponteiro ou uma referência de idioma). É importante observar que esse método remove um único nível de semântica de referência no objeto. É totalmente possível, por exemplo, ter uma referência de modelo de dados a uma referência de idioma. Nesse caso, chamar o método Dereference pela primeira vez removeria a referência do modelo de dados e deixaria a referência de idioma. Chamar Dereferência nesse objeto resultante removeria posteriormente a referência de idioma e retornaria o valor nativo sob essa referência.

métodos de manipulação de chave

Qualquer objeto sintético que seja um dicionário de tuplas de chave, valor e metadados tem uma série de métodos para manipular essas chaves, valores e metadados associados a eles.

As formas baseadas em valor das APIs são:

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;

Os formulários baseados em referência das APIs são:

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

O método GetKeyValue é o primeiro método ao qual um cliente recorrerá para obter o valor (e os metadados associados a) uma determinada chave por nome. Se a chave for um acessador de propriedade , ou seja, seu valor como um IModelObject, que é um IModelPropertyAccessor em caixa, o método GetKeyValue chamará automaticamente o método GetValue do acessador de propriedades para recuperar o valor real.

SetKeyValue

O método SetKeyValue é o primeiro método ao qual um cliente recorrerá para definir o valor de uma chave. Esse método não pode ser usado para criar uma nova chave em um objeto. Ele definirá apenas o valor de uma chave existente. Observe que muitas chaves são somente leitura (por exemplo: elas são implementadas por um acessador de propriedade que retorna E_NOT_IMPL de seu método SetValue). Esse método falhará quando chamado em uma chave somente leitura.

EnumerateKeyValues

O método EnumerateKeyValues é o primeiro método ao qual um cliente recorrerá para enumerar todas as chaves em um objeto (isso inclui todas as chaves implementadas em qualquer lugar na árvore dos modelos pai). É importante observar que EnumerateKeyValues enumerará todas as chaves definidas por nomes duplicados na árvore de objetos; no entanto , métodos como GetKeyValue e SetKeyValue manipularão apenas a primeira instância de uma chave com o nome fornecido, conforme descoberto pela passagem de profundidade.

GetKey

O método GetKey obterá o valor (e os metadados associados) de uma determinada chave por nome. Em vez disso, a maioria dos clientes deve utilizar o método GetKeyValue. Se a chave for um acessador de propriedade, chamar esse método retornará o acessador de propriedade (uma interface IModelPropertyAccessor) em caixa em um IModelObject. Ao contrário de GetKeyValue, esse método não resolverá automaticamente o valor subjacente da chave chamando o método GetValue. Essa responsabilidade é do chamador.

SetKey

O método SetKey é o método ao qual um cliente recorrerá para criar uma chave em um objeto (e potencialmente associar metadados à chave criada). Se um determinado objeto já tiver uma chave com o nome fornecido, um dos dois comportamentos ocorrerá. Se a chave estiver na instância fornecida por isso, o valor dessa chave será substituído como se a chave original não existisse. Se, por outro lado, a chave estiver na cadeia de modelos de dados pai da instância fornecida por isso, uma nova chave com o nome fornecido será criada na instância fornecida por isso. Isso, na verdade, faria com que o objeto tivesse duas chaves de mesmo nome (semelhante a uma classe derivada sombreando um membro com o mesmo nome de uma classe base).

EnumerateKeys

O método EnumerateKeys se comporta de forma semelhante ao método EnumerateKeyValues, exceto pelo fato de não resolver automaticamente os acessadores de propriedade no objeto. Isso significa que, se o valor de uma chave for um acessador de propriedade, o método EnumerateKeys retornará o acessador de propriedade (um IModelPropertyAccessorInterface) em caixa em um IModelObject em vez de chamar automaticamente o método GetValue. Isso é semelhante à diferença entre GetKey e GetKeyValue.

ClearKeys

O método ClearKeys remove todas as chaves e seus valores e metadados associados da instância do objeto especificada por isso. Esse método não tem efeito sobre os modelos pai anexados à instância de objeto específica.

GetKeyReference

O método GetKeyReference procurará uma chave do nome fornecido no objeto (ou sua cadeia de modelo pai) e retornará uma referência a essa chave fornecida por uma interface IModelKeyReference encaixada em um IModelObject. Essa referência pode ser usada posteriormente para obter ou definir o valor da chave.

EnumerateKeyReferences

O método EnumerateKeyReferences comporta-se semelhante ao método EnumerateKeyValues, exceto pelo fato de retornar referências às chaves que ele enumera (fornecido por uma interface IModelKeyReference encaixada em um IModelObject) em vez do valor da chave. Essas referências podem ser usadas para obter ou definir o valor subjacente das chaves.

métodos de manipulação de conceito

Além de um objeto de modelo ser um dicionário de tuplas de chave/valor/metadados, ele também é um contêiner de conceitos. Um conceito é algo abstrato que pode ser executado em ou por um objeto. Os conceitos são, em essência, um repositório dinâmico de interfaces que um objeto dá suporte. Vários conceitos são definidos pelo modelo de dados atualmente:

Interface de conceito Descrição
IDataModelConcept O conceito é um modelo pai. Se esse modelo for anexado automaticamente a um tipo nativo por meio de uma assinatura de tipo registrado, o método InitializeObject será automaticamente chamado sempre que um novo objeto desse tipo for instanciado.
IStringDisplayableConcept O objeto pode ser convertido em uma cadeia de caracteres para fins de exibição.
IIterableConcept O objeto é um contêiner e pode ser iterado.
IIndexableConcept O objeto é um contêiner e pode ser indexado (acessado por meio de acesso aleatório) em uma ou mais dimensões.
IPreferredRuntimeTypeConcept O objeto entende mais sobre tipos derivados dele do que o sistema de tipo subjacente é capaz de fornecer e gostaria de lidar com suas próprias conversões de tipo estático para runtime.
IDynamicKeyProviderConcept O objeto é um provedor dinâmico de chaves e deseja assumir todas as principais consultas do modelo de dados principal. Essa interface normalmente é usada como uma ponte para linguagens dinâmicas, como JavaScript.
IDynamicConceptProviderConcept O objeto é um provedor dinâmico de conceitos e deseja assumir todas as consultas conceituais do modelo de dados principal. Essa interface normalmente é usada como uma ponte para linguagens dinâmicas, como JavaScript.

Os métodos a seguir no IModelObject são utilizados para manipular os conceitos aos quais um objeto dá suporte.

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

O método GetConcept procurará um conceito no objeto (ou em sua cadeia de modelo pai) e retornará um ponteiro de interface para a interface de conceito. O comportamento e os métodos em uma interface de conceito são específicos para cada conceito. No entanto, é importante observar que muitas das interfaces de conceito exigem que o chamador passe explicitamente o objeto de contexto (ou o que se pode chamar tradicionalmente esse ponteiro). É importante garantir que o objeto de contexto correto seja passado para cada interface de conceito.

SetConcept

O método SetConcept colocará um conceito especificado na instância de objeto especificada pelo ponteiro. Se um modelo pai anexado à instância de objeto especificada por isso também der suporte ao conceito, a implementação na instância substituirá no modelo pai.

ClearConcepts

O método ClearConcepts removerá todos os conceitos da instância do objeto especificada por isso.

métodos de objeto nativo

Embora muitos objetos de modelo se refiram a intrínsecos (por exemplo: inteiros, cadeias de caracteres) ou construções sintéticas (um dicionário de tuplas e conceitos de chave/valor/metadados), um objeto de modelo também pode se referir a um constructo nativo (por exemplo: um tipo definido pelo usuário no espaço de endereço do destino de depuração). A interface IModelObject tem uma série de métodos que acessam informações sobre esses objetos nativos. Esses métodos são:

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

O método GetRawValue localiza uma construção nativa dentro do objeto fornecido. Esse constructo pode ser um campo, uma classe base, um campo em uma classe base, uma função membro etc...

EnumerateRawValues

O método EnumerateRawValues enumera todas as crianças nativas (por exemplo: campos, classes base etc...) do objeto fornecido.

TryCastToRuntimeType

O método TryCastToRuntimeType solicitará que o host de depuração execute uma análise e determine o tipo de runtime real (por exemplo, a classe mais derivada) do objeto fornecido. A análise exata utilizada é específica para o host de depuração e pode incluir RTTI (informações de tipo de tempo de execução C++), exame da estrutura V-Table(tabela de funções virtuais) do objeto ou qualquer outro meio que o host possa usar para determinar de forma confiável o tipo dinâmico/runtime do tipo estático. Falha ao converter em um tipo de runtime não significa que essa chamada de método falhará. Nesses casos, o método retornará o objeto fornecido (este ponteiro) no argumento de saída.

getLocation

O método GetLocation retornará o local do objeto nativo. Embora esse local normalmente seja um endereço virtual dentro do espaço de endereço do destino de depuração, ele não é necessariamente assim. O local retornado por esse método é um local abstrato que pode ser um endereço virtual, pode indicar o posicionamento em um registro ou sub-registro ou pode indicar algum outro espaço de endereço arbitrário, conforme definido pelo host de depuração. Se o campo HostDefined do objeto Location resultante for 0, ele indicará que o local é, na verdade, um endereço virtual. Esse endereço virtual pode ser recuperado examinando o campo Deslocamento do local resultante. Qualquer valor diferente de zero do campo HostDefined indica um espaço de endereço alternativo em que o campo Deslocamento é o deslocamento dentro desse espaço de endereço. O significado exato de valores HostDefined não zero aqui são privados para o host de depuração.

GetTypeInfo

O método GetTypeInfo retornará o tipo nativo do objeto fornecido. Se o objeto não tiver informações de tipo nativo associadas a ele (por exemplo: ele é intrínseco, etc...), a chamada ainda terá êxito, mas retornará nulo.

GetTargetInfo

O método GetTargetInfo é efetivamente uma combinação dos métodos GetLocation e GetTypeInfo retornando tanto o local abstrato quanto o tipo nativo do objeto fornecido.

GetRawReference

O método GetRawReference localiza uma construção nativa dentro do objeto fornecido e retorna uma referência a ele. Esse constructo pode ser um campo, uma classe base, um campo em uma classe base, uma função membro etc... É importante distinguir a referência retornada aqui (um objeto do tipo ObjectTargetObjectReference) de uma referência de linguagem (por exemplo: uma referência de estilo de & ou && C++).

EnumerateRawReferences

O método EnumerateRawReferences enumera referências a todas as crianças nativas (por exemplo: campos, classes base etc...) do objeto fornecido.

métodos de extensibilidade

Conforme descrito anteriormente, um objeto modelo se comporta muito semelhante a um objeto JavaScript e sua cadeia de protótipos. Além da instância representada por uma determinada interface IModelObject, pode haver um número arbitrário de modelos pai anexados ao objeto (cada um deles pode, por sua vez, ter um número arbitrário de modelos pai anexados a eles). Esse é o principal meio de extensibilidade dentro do modelo de dados. Se uma determinada propriedade ou conceito não puder ser localizado dentro de uma determinada instância, uma pesquisa detalhada da árvore de objetos (definida por modelos pai) com raiz na instância será executada.

Os métodos a seguir manipulam a cadeia de modelos pai associados a uma determinada instância 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

O método GetNumberOfParentModels retorna o número de modelos pai anexados à instância de objeto fornecida. Os modelos pai são pesquisados em busca de propriedades detalhadas na ordenação linear da cadeia de modelos pai.

GetParentModel

O método GetParentModel retorna o modelo pai i-th na cadeia de modelo pai do objeto fornecido. Os modelos pai são pesquisados por uma propriedade ou conceito na ordem linear em que são adicionados ou enumerados. O modelo pai com índice i de zero é pesquisado (hierarquicamente) antes do modelo pai com índice i + 1.

AddParentModel

O método AddParentModel adiciona um novo modelo pai ao objeto fornecido. Esse modelo pode ser adicionado no final da cadeia de pesquisa (o argumento de substituição é especificado como false) ou na frente da cadeia de pesquisa (o argumento de substituição é especificado como true). Além disso, cada modelo pai pode, opcionalmente, ajustar o contexto (a semântica deste ponteiro) para qualquer propriedade ou conceito no pai determinado (ou qualquer pessoa em sua hierarquia pai). O ajuste de contexto raramente é usado, mas permite alguns conceitos poderosos, como a inserção de objetos, a construção de namespaces etc...

RemoveParentModel

O RemoveParentModel removerá um modelo pai especificado da cadeia de pesquisa pai do objeto fornecido.

SetContextForDataModel

O método SetContextForDataModel é usado pela implementação de um modelo de dados para colocar dados de implementação em objetos de instância. Conceitualmente, cada IModelObject (chame essa instância para simplificar) contém uma tabela de estado de hash. A tabela de hash é indexada por outro IModelObject (chame-o de modelo de dados para simplificar), que está na hierarquia de modelo pai da instância. O valor contido nesse hash é um conjunto de informações de estado contadas de referência representadas por uma instância IUnknown. Depois que o modelo de dados define esse estado na instância, ele pode armazenar dados arbitrários de implementação que podem ser recuperados durante itens como getters de propriedade.

GetContextForDataModel

O método GetContextForDataModel é usado para recuperar informações de contexto que foram configuradas com uma chamada anterior para SetContextForDataModel. Isso recupera informações de estado que foram definidas em um objeto de instância por um modelo de dados mais acima na hierarquia de modelo pai do objeto de instância. Para obter mais detalhes sobre esse contexto/estado e seu significado, consulte a documentação de SetContextForDataModel.

tipos de objeto core do modelo de dados do depurador

Um objeto no modelo de dados é semelhante à noção de Objeto no .NET. É o contêiner genérico no qual o constructo que o modelo de dados entende pode ser boxizado. Além de objetos nativos e objetos sintéticos (dinâmicos), há uma série de tipos de objetos principais que podem ser colocados (ou em caixa) no contêiner de um IModelObject. O contêiner no qual a maioria desses valores são colocados é um COM/OLE VARIANT padrão com uma série de restrições adicionais colocadas sobre o que esse VARIANT pode conter. Os tipos mais básicos são:

  • Valores assinados e sem sinal de 8 bits (VT_UI1, VT_I1)
  • Valores assinados e sem sinal de 16 bits (VT_UI2, VT_UI2)
  • Valores assinados e sem sinal de 32 bits (VT_UI4, VT_I4)
  • Valores sem sinal e assinados de 64 bits (VT_UI8, VT_I8)
  • Valores de ponto flutuante de precisão única e dupla (VT_R4, VT_R8)
  • Cadeias de caracteres (VT_BSTR)
  • Boolianos (VT_BOOL)

Além desses tipos básicos, vários objetos principais do modelo de dados são colocados em IModelObject definidos por VT_UNKNOWN em que o IUnknown armazenado tem a garantia de implementar uma interface específica. Esses tipos são:

  • Acessadores de propriedade (IModelPropertyAccessor)
  • Objetos de método (IModelMethod)
  • Objetos de referência de chave (IModelKeyReference ou IModelKeyReference2)
  • Objetos de contexto (IDebugModelHostContext)

Acessadores de propriedade : IModelPropertyAccessor

Um acessador de propriedade no modelo de dados é uma implementação da interface IModelPropertyAccessor que é encaixada em um IModelObject. O objeto modelo retornará um tipo de ObjectPropertyAccessor quando consultado e o valor intrínseco é um VT_UNKNOWN que tem a garantia de ser consultável para IModelPropertyAccessor. No processo, é garantido que ele seja estaticamente castível para IModelPropertyAccessor.

Um acessador de propriedade é uma maneira indireta de obter uma chamada de método para obter e definir um valor de chave no modelo de dados. Se o valor de uma determinada chave for um acessador de propriedade, os métodos GetKeyValue e SetKeyValue observarão isso automaticamente e chamarão os métodos GetValue ou SetValue subjacentes do acessador de propriedade, conforme apropriado.

A interface IModelPropertyAccessor é definida da seguinte maneira:

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

O método GetValue é o getter para o acessador de propriedade. Ele é chamado sempre que um cliente deseja buscar o valor subjacente da propriedade. Observe que qualquer chamador que obtém diretamente um acessador de propriedade é responsável por passar o nome da chave e o objeto de instância precisa (este ponteiro) para o método GetValue do acessador de propriedade.

SetValue

O método SetValue é o setter para o acessador de propriedade. Ele é chamado sempre que um cliente deseja atribuir um valor à propriedade subjacente. Muitas propriedades são somente leitura. Nesses casos, chamar o método SetValue retornará E_NOTIMPL. Observe que qualquer chamador que obtém diretamente um acessador de propriedade é responsável por passar o nome da chave e o objeto de instância precisa (este ponteiro) para o método SetValue do acessador de propriedade.

Métodos : IModelMethod

Um método no modelo de dados é uma implementação da interface IModelMethod que é encaixada em um IModelObject. O objeto modelo retornará um tipo de ObjectMethod quando consultado e o valor intrínseco é um VT_UNKNOWN que é garantido como consultável para IModelMethod. No processo, é garantido que ele seja estaticamente castível para IModelMethod. Todos os métodos no modelo de dados são dinâmicos por natureza. Eles tomam como entrada um conjunto de 0 ou mais argumentos e retornam um único valor de saída. Não há resolução de sobrecarga e nem metadados sobre nomes de parâmetros, tipos ou expectativas.

A interface IModelMethod é definida da seguinte maneira:

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;
}

Chamar

O método Call é a maneira como qualquer método definido no modelo de dados é invocado. O chamador é responsável por passar um objeto de instância preciso (este ponteiro) e um conjunto arbitrário de argumentos. O resultado do método e todos os metadados opcionais associados a esse resultado são retornados. Os métodos que não retornam logicamente um valor ainda devem retornar um IModelObject válido. Nesse caso, o IModelObject é um valor sem valor em caixa. Caso um método falhe, ele poderá retornar informações de erro estendidas opcionais no argumento de entrada (mesmo que o HRESULT retornado seja uma falha). É imperativo que os chamadores verifiquem isso.

Referências de chave : IModelKeyReference ou IModelKeyReference2

Uma referência de chave é, em essência, um identificador para uma chave em um objeto específico. Um cliente pode recuperar esse identificador por meio de métodos como GetKeyReference e usar o identificador posteriormente para obter ou definir o valor da chave sem necessariamente manter o objeto original. Esse tipo de objeto é uma implementação da interface IModelKeyReference ou IModelKeyReference2 que é encaixada em um IModelObject. O objeto modelo retornará um tipo de ObjectKeyReference quando consultado e, em seguida, o valor intrínseco é um VT_UNKNOWN que é garantido como consultável para IModelKeyReference. No processo, é garantido que ele seja estaticamente castível para IModelKeyReference.

A interface de referência de chave é definida da seguinte maneira:

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

O método GetKeyName retorna o nome da chave à qual essa referência de chave é um identificador. A cadeia de caracteres retornada é um BSTR padrão e deve ser liberada por meio de uma chamada para SysFreeString.

GetOriginalObject

O método GetOriginalObject retorna o objeto de instância do qual a referência de chave foi criada. Observe que a chave pode estar em um modelo pai do objeto de instância.

GetContextObject

O método GetContextObject retorna o contexto (este ponteiro) que será passado para o método GetValue ou SetValue de um acessador de propriedade se a chave em questão se referir a um acessador de propriedade. O objeto de contexto retornado aqui pode ou não ser o mesmo que o objeto original buscado de GetOriginalObject. Se uma chave estiver em um modelo pai e houver um ajuste de contexto associado a esse modelo pai, o objeto original será o objeto de instância no qual GetKeyReference ou EnumerateKeyReferences foi chamado. O objeto de contexto seria o que sair do ajuste de contexto final entre o objeto original e o modelo pai que contém a chave à qual essa referência de chave é um identificador. Se não houver ajustes de contexto, o objeto original e o objeto de contexto serão idênticos.

GetKey

O método GetKey em uma referência de chave se comporta como o método GetKey em IModelObject faria. Ele retorna o valor da chave subjacente e todos os metadados associados à chave. Se o valor da chave for um acessador de propriedade, isso retornará o acessador de propriedade (IModelPropertyAccessor) em caixa em um IModelObject. Esse método não chamará os métodos GetValue ou SetValue subjacentes no acessador de propriedade.

GetKeyValue

O método GetKeyValue em uma referência de chave se comporta como o método GetKeyValue em IModelObject. Ele retorna o valor da chave subjacente e todos os metadados associados à chave. Se o valor da chave for um acessador de propriedade, isso chamará automaticamente o método GetValue subjacente no acessador de propriedade.

SetKey

O método SetKey em uma referência de chave se comporta como o método SetKey em IModelObject faria. Ele atribuirá o valor da chave. Se a chave original fosse um acessador de propriedade, isso substituirá o acessador de propriedade. Ele não chamará o método SetValue no acessador de propriedade.

SetKeyValue

O método SetKeyValue em uma referência de chave se comporta como o método SetKeyValue em IModelObject. Ele atribuirá o valor da chave. Se a chave original fosse um acessador de propriedade, isso chamará o método SetValue subjacente no acessador de propriedade em vez de substituir o próprio acessador de propriedade.

OverrideContextObject

O método OverrideContextObject (presente apenas em IModelKeyReference2) é um método avançado que é usado para alterar permanentemente o objeto de contexto que essa referência de chave passará para os métodos GetValue ou SetValue de qualquer acessador de propriedade subjacente. O objeto passado para esse método também será retornado de uma chamada para GetContextObject. Esse método pode ser usado por provedores de script para replicar determinados comportamentos dinâmicos de linguagem. A maioria dos clientes não deve chamar esse método.

objetos de contexto : IDebugHostContext

Objetos de contexto são blobs opacos de informações que o host de depuração (em cooperação com o modelo de dados) associa a cada objeto. Pode incluir itens como o contexto do processo ou o espaço de endereço do qual as informações vêm, etc... Um objeto de contexto é uma implementação de IDebugHostContext em caixa dentro de um IModelObject. Observe que IDebugHostContext é uma interface definida pelo host. Um cliente nunca implementará essa interface.

Para obter mais informações sobre objetos de contexto, consulte Interfaces de host C++ do Modelo de Dados do Depurador em Interfaces C++ do Modelo de Dados do Depurador.

o Gerenciador de Modelos de Dados

A interface principal para o gerenciador de modelos de dados, IDataModelManager2 (ou o IDataModelManager anterior) é definida da seguinte maneira:

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;
}

métodos de gerenciamento

O seguinte conjunto de métodos é utilizado pelo aplicativo (por exemplo, depurador) que hospeda o modelo de dados.

STDMETHOD(Close)() PURE;

Fechar

O método Close é chamado no gerenciador de modelos de dados por um aplicativo (por exemplo, depurador) que hospeda o modelo de dados para iniciar o processo de desligamento do gerenciador de modelos de dados. Um host do modelo de dados que não faz o método Close antes de lançar sua referência final no gerenciador de modelos de dados pode causar um comportamento indefinido, incluindo, mas não se limitando a, vazamentos significativos da infraestrutura de gerenciamento para o modelo de dados.

criação de objeto /métodos boxing

O seguinte conjunto de métodos é usado para criar novos objetos ou para agrupar valores em um IModelObject , a interface principal do modelo de dados.

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

O método CreateNoValue cria um objeto "sem valor", o coloca em um IModelObject e o retorna. O objeto de modelo retornado tem um tipo de ObjectNoValue.

Um objeto "sem valor" tem vários significados semânticos:

  • (Dependendo da linguagem), ele pode ser considerado o equivalente semântico de nulo, nulo ou indefinido
  • O método GetValue de qualquer acessador de propriedade que retorna êxito e um objeto "sem valor" resultante indica que a propriedade específica não tem valor para a instância determinada e deve ser tratada como se a propriedade não existisse para essa instância específica.
  • Métodos de modelo de dados que não têm um valor retornado semanticamente usam isso como sentinela para indicar tal (como um método deve retornar um IModelObject válido).

CreateErrorObject

O método CreateErrorObject cria um "objeto de erro". O modelo de dados não tem a noção de exceções e fluxo de exceção. A falha sai de uma propriedade/método de duas maneiras:

  • Um HRESULT com falha única sem informações de erro estendidas. Não há mais informações que possam ser fornecidas para o erro ou o erro em si é autoexplicativo do HRESULT retornado.
  • Um HRESULT com falha única, juntamente com informações de erro estendidas. As informações de erro estendidas são um objeto de erro retornado no argumento de saída da propriedade/método.

CreateTypedObject

O método CreateTypedObject é o método que permite que um cliente crie uma representação de um objeto nativo/idioma no espaço de endereço de um destino de depuração. Se o tipo do objeto recém-criado (conforme indicado pelo argumento objectType) corresponder a uma ou mais assinaturas de tipo registradas com o gerenciador de modelos de dados como visualizadores canônicos ou extensões, esses modelos de dados correspondentes serão anexados automaticamente ao objeto de instância criado antes de serem retornados ao chamador.

CreateTypedObjectReference

O método CreateTypedObjectReference é semanticamente semelhante ao método CreateTypedObject, exceto pelo fato de criar uma referência ao constructo nativo/idioma subjacente. A referência criada é um objeto que tem um tipo de ObjectTargetObjectReference. Não é uma referência nativa, pois a linguagem subjacente pode dar suporte (por exemplo: um & C++ ou &&). É totalmente possível ter um ObjectTargetObjectReference para uma referência C++. Um objeto do tipo ObjectTargetObjectReference pode ser convertido no valor subjacente por meio do uso do método Dereference em IModelObject. A referência também pode ser passada para o avaliador de expressão do host subjacente para atribuir de volta ao valor de maneira apropriada.

CreateSyntheticObject

O método CreateSyntheticObject cria um objeto de modelo de dados vazio: um dicionário de tuplas e conceitos de chave/valor/metadados. No momento da criação, não há chaves nem conceitos no objeto. É uma ficha limpa para o chamador utilizar.

CreateDataModelObject

O método CreateDataModelObject é um wrapper auxiliar simples para criar objetos que são modelos de dados, ou seja, objetos que serão anexados como modelos pai a outros objetos. Todos esses objetos devem dar suporte ao conceito de modelo de dados por meio de IDataModelConcept. Esse método cria um novo objeto sintético em branco sem contexto explícito e adiciona o IDataModelConcept inpassado como a implementação do objeto recém-criado do conceito de modelo de dados. Isso também pode ser feito com chamadas para CreateSyntheticObject e SetConcept.

CreateIntrinsicObject

O método CreateIntrinsicObject é o método que coloca valores intrínsecos em IModelObject. O chamador coloca o valor em um COM VARIANT e chama esse método. O gerenciador de modelos de dados retorna um IModelObject que representa o objeto. Observe que esse método também é usado para fazer a caixa de tipos básicos baseados em IUnknown: acessadores de propriedade, métodos, contextos etc... Nesses casos, o método objectKind indica que tipo de construção baseada em IUnknown o objeto representa e o campo punkVal da variante passada é o tipo derivado de IUnknown. O tipo deve ser castível estaticamente para a interface de modelo apropriada (por exemplo: IModelPropertyAccessor, IModelMethod, IDebugHostContext etc...) em processo. Os tipos VARIANT compatíveis com esse método são VT_UI1, VT_I1, VT_UI2, VT_I2, VT_UI4, VT_I4, VT_UI8, VT_I8, VT_R4, VT_R8, VT_BOOL, VT_BSTR e VT_UNKNOWN (para um conjunto especializado de tipos derivados IUnknown, conforme indicado pela enumeração ModelObjectKind.

CreateTypedIntrinsicObject

O método CreateTypedintrinsicObject é semelhante ao método CreateIntrinsicObject, exceto por permitir que um tipo nativo/idioma seja associado aos dados e levado junto com o valor em caixa. Isso permite que o modelo de dados represente constructos como tipos de enumeração nativos (que são simplesmente valores VT_UI* ou VT_I*). Tipos de ponteiro também são criados com esse método. Um ponteiro nativo no modelo de dados é uma quantidade de 64 bits estendida zero que representa um deslocamento para o espaço de endereço virtual do destino de depuração. Ele está em caixa dentro de um VT_UI8 e é criado com esse método e um tipo que indica um ponteiro nativo/idioma.

CreateMetadataStore

O método CreateMetadataStore cria um repositório de chaves , um contêiner simplificado de tuplas de chave/valor/metadados, que é usado para conter metadados que podem ser associados a propriedades e uma variedade de outros valores. Um repositório de metadados pode ter um único pai (que, por sua vez, pode ter um único pai). Se uma determinada chave de metadados não estiver localizada em um determinado repositório, seus pais serão verificados. A maioria dos repositórios de metadados não tem pais. No entanto, ele fornece uma maneira de compartilhar metadados comuns facilmente.

CreateTypedIntrinsicObjectEx

O método CreateTypedIntrinsicObjectEx é semanticamente semelhante ao método CreateTypedIntrinsicObject. A única diferença entre os dois é que esse método permite que o chamador especifique o contexto no qual os dados intrínsecos são válidos. Se nenhum contexto for passado, os dados serão considerados válidos em qualquer contexto herdado do argumento type (como CreateTypedIntrinsicObject se comporta). Isso permite a criação de valores de ponteiro tipados no destino de depuração que exigem um contexto mais específico do que pode ser herdado do tipo.

Extensibilidade/Métodos de Registro O seguinte conjunto de métodos gerencia o mecanismo de extensibilidade do modelo de dados, permitindo que um cliente estenda ou registre modelos existentes ou peça ao modelo de dados para anexar automaticamente um determinado modelo pai em tipos nativos que correspondam a um determinado critério.

    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

O método GetModelForTypeSignature retorna o modelo de dados que foi registrado em uma assinatura de tipo específica por meio de uma chamada anterior ao método RegisterModelForTypeSignature. O modelo de dados retornado desse método é considerado o visualizador canônico para qualquer tipo que corresponda à assinatura de tipo passada. Como visualizador canônico, esse modelo de dados assume a exibição do tipo. Os mecanismos de exibição ocultarão, por padrão, construções nativas/de idioma do objeto em favor da exibição do objeto apresentado pelo modelo de dados.

GetModelForType

O método GetModelForType retorna o modelo de dados que é o visualizador canônico de uma determinada instância de tipo. Na verdade, esse método encontra a melhor assinatura de tipo de correspondência que foi registrada com uma chamada anterior ao método RegisterModelForTypeSignature e retorna o modelo de dados associado.

RegisterModelForTypeSignature

O método RegisterModelForTypeSignature é o método primário que um chamador utiliza para registrar um visualizador canônico para um determinado tipo (ou conjunto de tipos). Um visualizador canônico é um modelo de dados que, na verdade, assume a exibição de um determinado tipo (ou conjunto de tipos). Em vez do modo de exibição nativo/idioma do tipo que está sendo exibido em qualquer interface do usuário do depurador, a exibição do tipo apresentada pelo modelo de dados registrado é exibida (juntamente com um meio de voltar ao modo de exibição nativo/idioma para um usuário que o deseja).

UnregisterModelForTypeSignature

O método UnregisterModelForTypeSignature desfaz uma chamada anterior ao método RegisterModelForTypeSignature. Esse método pode remover um determinado modelo de dados como visualizador canônico para tipos que correspondem a uma assinatura de tipo específico ou pode remover um determinado modelo de dados como visualizador canônico para cada assinatura de tipo sob a qual esse modelo de dados é registrado.

RegisterExtensionForTypeSignature

O método RegisterExtensionForTypeSignature é semelhante ao método RegisterModelForTypeSignature com uma diferença de chave. O modelo de dados que é passado para esse método não é o visualizador canônico para qualquer tipo e não assumirá a exibição do modo de exibição nativo/idioma desse tipo. O modelo de dados que é passado para esse método será automaticamente adicionado como pai a qualquer tipo concreto que corresponda à assinatura de tipo fornecida. Ao contrário do método RegisterModelForTypeSignature, não há limite para assinaturas de tipo idênticas ou ambíguas sendo registradas como extensões para um determinado tipo (ou conjunto de tipos). Cada extensão cuja assinatura de tipo corresponde a uma determinada instância de tipo concreto fará com que o modelo de dados registrado por meio desse método seja anexado automaticamente a objetos recém-criados como modelos pai. Isso, na verdade, permite que um número arbitrário de clientes estenda um tipo (ou conjunto de tipos) com novos campos ou funcionalidades.

unregisterExtensionForTypeSignature

O método UnregisterExtensionForTypeSignature desfaz uma chamada anterior para RegisterExtensionForTypeSignature. Ele cancela o registro de um modelo de dados específico como uma extensão para uma assinatura de tipo específico ou como uma extensão para todas as assinaturas de tipo em que o modelo de dados foi registrado.

GetRootNamespace

O método GetRootNamespace retorna o namespace raiz do modelo de dados. Esse é um objeto que o modelo de dados gerencia e no qual o host de depuração coloca determinados objetos.

RegisterNamedModel

O método RegisterNamedModel registra um determinado modelo de dados em um nome conhecido para que ele possa ser encontrado por clientes que desejam estendê-lo. Essa é a principal finalidade da API : publicar um modelo de dados como algo que pode ser estendido recuperando o modelo registrado sob esse nome conhecido e adicionando um modelo pai a ele.

UnregisterNamedModel

O método UnregisterNamedModel desfaz uma chamada anterior para RegisterNamedModel. Ele remove a associação entre um modelo de dados e um nome no qual ele pode ser pesquisado.

AcquireNamedModel

Um chamador que deseja estender um modelo de dados registrado em um determinado nome chama o método AcquireNamedModel para recuperar o objeto para o modelo de dados que deseja estender. Esse método retornará qualquer modelo de dados registrado por meio de uma chamada anterior ao método RegisterNamedModel. Como a principal finalidade do método AcquireNamedModel é estender o modelo, esse método terá um comportamento especial se nenhum modelo tiver sido registrado no nome fornecido ainda. Se nenhum modelo tiver sido registrado no nome fornecido ainda, um objeto stub será criado, registrado temporariamente sob o nome fornecido e retornado ao chamador. Quando o modelo de dados real é registrado por meio de uma chamada para o método RegisterNamedModel, todas as alterações feitas no objeto stub são, de fato, feitas no modelo real. Isso remove muitos problemas de dependência de ordem de carga de componentes que se estendem entre si.

métodos auxiliares

Os métodos a seguir são métodos auxiliares gerais que ajudam a executar operações complexas em objetos no modelo de dados. Embora seja possível executar essas ações por meio de outros métodos no modelo de dados ou em seus objetos, esses métodos de conveniência facilitam significativamente:

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

AcquireSubNamespace

O método AcquireSubNamespace ajuda na construção de algo que pode ser mais tradicionalmente parecido com um namespace de linguagem do que um novo objeto em uma linguagem dinâmica. Se, por exemplo, um chamador quiser categorizar as propriedades em um objeto de processo para tornar o objeto de processo mais organizado e as propriedades mais fáceis de descobrir, um método de fazer isso seria criar um subprojeto para cada categoria no objeto de processo e colocar essas propriedades dentro desse objeto.

Consulte também

Este tópico faz parte de uma série que descreve as interfaces acessíveis do C++, como usá-las para criar uma extensão de depurador baseada em C++ e como usar outras construções de modelo de dados (por exemplo: JavaScript ou NatVis) de uma extensão de modelo de dados C++.

Visão geral do modelo de dados do depurador C++

interfaces C++ do modelo de dados do depurador de

interfaces adicionais C++ do modelo de dados do depurador

conceitos do C++ do modelo de dados do depurador

de script C++ do modelo de dados do depurador