Oggetti C++ del modello di dati del debugger

In questo argomento viene descritto come usare oggetti C++ del modello di dati del debugger e come estendere le funzionalità del debugger.

Modello a oggetti del debugger principale

Uno degli aspetti più semplici e potenti del modello di dati è che standardizza la definizione di ciò che un oggetto è e il modo in cui interagisce con un oggetto. L'interfaccia IModelObject incapsula la nozione di un oggetto, indipendentemente dal fatto che l'oggetto sia un numero intero, un valore a virgola mobile, una stringa, un tipo complesso nello spazio indirizzi di destinazione del debugger o un concetto di debugger come la nozione di un processo o di un modulo.

Esistono diversi elementi che possono essere mantenuti in (o boxed in) in un IModelObject:

  • Valori intrinseci : un oggetto IModelObject può essere un contenitore per diversi tipi di base: 8, 16, 32 o integer senza segno a 64 bit, valori booleani, stringhe, errori o la nozione di valori vuoti.

  • Oggetti nativi : un IModelObject può rappresentare un tipo complesso (come definito dal sistema di tipi del debugger) all'interno dello spazio indirizzi di qualsiasi destinazione del debugger

  • Oggetti sintetici : un oggetto IModelObject può essere un oggetto dinamico, ovvero un dizionario se si vuole: una raccolta di tuple chiave/valore/metadati e un set di concetti che definiscono i comportamenti che non sono semplicemente rappresentati da coppie chiave/valore.

  • Proprietà : un IModelObject può rappresentare una proprietà: un elemento il cui valore può essere recuperato o modificato con una chiamata al metodo. Una proprietà all'interno di un IModelObject è in effetti un'interfaccia IModelPropertyAccessor boxed in un IModelObject

  • Metodi : un IModelObject può rappresentare un metodo: un oggetto che è possibile chiamare con un set di argomenti e ottenere un valore restituito. Un metodo all'interno di un IModelObject è effettivamente un'interfaccia IModelMethod boxed in un IModelObject

Estendibilità all'interno del modello a oggetti

Un IModelObject non è un oggetto in isolamento. Oltre a rappresentare uno dei tipi di oggetti illustrati in precedenza, ogni oggetto ha la nozione di una catena di modelli di dati padre. Questa catena si comporta in modo molto simile a una catena di prototipi JavaScript. Anziché una catena lineare di prototipi come JavaScript, ogni oggetto modello di dati definisce una catena lineare di modelli padre. Ognuno di questi modelli padre a sua volta ha un'altra catena lineare del proprio set di elementi padre. In sostanza, ogni oggetto è un'aggregazione delle funzionalità (proprietà e così via) di se stesso e di ogni oggetto in questo albero. Quando viene eseguita una query su una proprietà specifica, se l'oggetto su cui viene eseguita una query non supporta tale proprietà, la query viene passata in ordine lineare a ogni elemento padre. In questo modo viene creato un comportamento in cui la ricerca di una proprietà viene risolta da una ricerca depth-first dell'albero di aggregazione.

L'estendibilità all'interno di questo modello a oggetti è molto semplice dato che ogni oggetto è un'aggregazione di se stessa e l'albero dei modelli padre. Un'estensione può entrare e aggiungersi all'elenco dei modelli padre per un altro oggetto . In questo modo l'oggetto viene esteso . In questo modo, è possibile aggiungere funzionalità a qualsiasi elemento: una particolare istanza di un oggetto o un valore, un tipo nativo, il concetto del debugger di un processo o di un thread o persino la nozione di "tutti gli oggetti iterabili".

Contesto, contesto e contesto: puntatore , spazio indirizzi e dati privati di implementazione

Esistono tre nozioni di contesto necessarie per comprendere nel contesto del modello a oggetti.

Contesto: puntatore

Poiché una determinata proprietà o metodo può essere implementato a qualsiasi livello dell'albero del modello di dati, è necessario che l'implementazione del metodo o della proprietà sia in grado di accedere all'oggetto originale (ciò che è possibile chiamare questo puntatore in C++ o l'oggetto in JavaScript). Tale oggetto istanza viene passato a un'ampia gamma di metodi come primo argomento denominato contesto nei metodi descritti.

Contesto: Spazio indirizzi

È importante notare che, a differenza dei modelli di estensione precedenti in cui il contesto (destinazione, processo, thread che si sta esaminando) è un concetto di interfaccia utente con tutte le API relative allo stato corrente dell'interfaccia utente, le interfacce del modello di dati in genere accettano questo contesto in modo esplicito o implicito come interfaccia IDebugHostContext . Ogni IModelObject all'interno del modello di dati contiene questo tipo di informazioni di contesto insieme a esso e può propagare tale contesto agli oggetti restituiti. Ciò significa che quando si legge un valore nativo o un valore di chiave da un oggetto IModelObject, il valore verrà letto dalla destinazione ed elaborato da cui l'oggetto è stato originariamente acquisito.

Esiste un valore costante esplicito, USE_CURRENT_HOST_CONTEXT, che può essere passato ai metodi che accettano un argomento IDebugHostContext . Questo valore indica che il contesto deve effettivamente essere lo stato corrente dell'interfaccia utente del debugger. Questo concetto, tuttavia, deve essere esplicito.

Contesto: Dati privati dell'implementazione

Tenere presente che ogni oggetto nel modello di dati è in realtà un'aggregazione dell'istanza dell'oggetto e l'albero dei modelli padre associati. Ognuno di questi modelli padre (che può essere collegato nelle catene di molti oggetti diversi) può associare dati di implementazione privata a qualsiasi oggetto istanza. Ogni IModelObject creato concettualmente ha una tabella hash che esegue il mapping da un modello padre specifico a dati di istanza privata definiti da un'interfaccia IUnknown . Ciò consente a un modello padre di memorizzare nella cache le informazioni su ogni istanza o di disporre di dati altrimenti arbitrari associati.

Questo tipo di contesto è accessibile tramite i metodi GetContextForDataModel e SetContextForDataModel in IModelObject.

Interfaccia oggetto del debugger principale: IModelObject


L'interfaccia IModelObject è definita come segue:

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

Metodi di base

Di seguito sono riportati i metodi generali applicabili a qualsiasi tipo di oggetto rappresentato da un 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

Il metodo GetKind restituisce il tipo di oggetto sottoposto a boxing all'interno di IModelObject.

GetContext

Il metodo GetContext restituisce il contesto host associato all'oggetto .

GetIntrinsicValue

Il metodo GetIntrinsicValue restituisce l'elemento sottoposto a boxing all'interno di un oggetto IModelObject. Questo metodo può essere chiamato legalmente solo sulle interfacce IModelObject che rappresentano un intrinseco boxed o una particolare interfaccia che viene boxed. Non può essere chiamato su oggetti nativi, oggetti valore, oggetti sintetici e oggetti di riferimento. Il metodo GetIntrinsicValueAs si comporta in modo molto simile al metodo GetIntrinsicValue, ad eccezione del fatto che converte il valore nel tipo variant specificato. Se la conversione non può essere eseguita, il metodo restituisce un errore.

IsEqualTo

Il metodo IsEqualTo confronta due oggetti modello e restituisce se sono uguali in valore. Per l'oggetto con un ordinamento, questo metodo che restituisce true equivale al metodo Compare che restituisce 0. Per gli oggetti che non dispongono di ordinamento ma sono equabili, il metodo Compare avrà esito negativo, ma non lo sarà. Il significato di un confronto basato su valori è definito dal tipo di oggetto. Attualmente, questo valore è definito solo per i tipi intrinseci e gli oggetti errore. Non esiste un concetto di modello di dati corrente per l'equatability.

Dereference

Il metodo Dereference dereferenzia un oggetto . Questo metodo può essere usato per dereferenziare un riferimento basato su un modello di dati (ObjectTargetObjectReference, ObjectKeyReference) o un riferimento al linguaggio nativo (un puntatore o un riferimento al linguaggio). È importante notare che questo metodo rimuove un singolo livello di semantica di riferimento nell'oggetto . È possibile, ad esempio, avere un riferimento al modello di dati a un riferimento al linguaggio. In tal caso, la prima volta che si chiama il metodo Dereference si rimuove il riferimento al modello di dati e si lascia il riferimento al linguaggio. La chiamata di Dereference su tale oggetto risultante rimuoverà successivamente il riferimento alla lingua e restituirà il valore nativo in tale riferimento.

Metodi di manipolazione delle chiavi

Qualsiasi oggetto sintetico che è un dizionario di tuple chiave, valore e metadati ha una serie di metodi per modificare tali chiavi, valori e metadati associati.

Le forme basate sui valori delle API sono:

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;

Le forme basate sui riferimenti delle API sono:

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

Il metodo GetKeyValue è il primo metodo a cui un client si rivolge per ottenere il valore di (e i metadati associati a) una determinata chiave in base al nome. Se la chiave è una funzione di accesso alla proprietà, ovvero il valore di un oggetto IModelObject che è un oggetto IModelPropertyAccessor boxed, il metodo GetKeyValue chiamerà automaticamente il metodo GetValue della funzione di accesso alla proprietà per recuperare il valore effettivo.

SetKeyValue

Il metodo SetKeyValue è il primo metodo a cui un client si rivolge per impostare il valore di una chiave. Questo metodo non può essere utilizzato per creare una nuova chiave in un oggetto . Imposterà solo il valore di una chiave esistente. Si noti che molte chiavi sono di sola lettura, ad esempio implementate da una funzione di accesso della proprietà che restituisce E_NOT_IMPL dal metodo SetValue. Questo metodo avrà esito negativo quando viene chiamato su una chiave di sola lettura.

EnumerateKeyValues

Il metodo EnumerateKeyValues è il primo metodo a cui un client si rivolge per enumerare tutte le chiavi in un oggetto (incluse tutte le chiavi implementate in qualsiasi punto dell'albero dei modelli padre). È importante notare che EnumerateKeyValues enumera tutte le chiavi definite dai nomi duplicati nell'albero degli oggetti; tuttavia, i metodi come GetKeyValue e SetKeyValue modificano solo la prima istanza di una chiave con il nome specificato come individuato dall'attraversamento depth-first-traversal.

GetKey

Il metodo GetKey otterrà il valore di (e i metadati associati a) una determinata chiave in base al nome. La maggior parte dei client deve utilizzare invece il metodo GetKeyValue. Se la chiave è una funzione di accesso alle proprietà, la chiamata a questo metodo restituirà la funzione di accesso della proprietà (un'interfaccia IModelPropertyAccessor) boxed in un IModelObject. A differenza di GetKeyValue, questo metodo non risolverà automaticamente il valore sottostante della chiave chiamando il metodo GetValue. Questa responsabilità è quella del chiamante.

Setkey

Il metodo SetKey è il metodo a cui un client si rivolge per creare una chiave in un oggetto (e potenzialmente associare metadati alla chiave creata). Se un determinato oggetto ha già una chiave con il nome specificato, si verificherà uno dei due comportamenti. Se la chiave si trova nell'istanza specificata da questo, il valore di tale chiave verrà sostituito come se la chiave originale non esistesse. Se, d'altra parte, la chiave si trova nella catena di modelli di dati padre dell'istanza specificata da questo, nell'istanza specificata verrà creata una nuova chiave con il nome specificato. Ciò comporterebbe, in effetti, che l'oggetto abbia due chiavi con lo stesso nome (analogamente a una classe derivata che shadowing di un membro con lo stesso nome di una classe di base).

EnumerateKeys

Il metodo EnumerateKeys si comporta in modo simile al metodo EnumerateKeyValues, ad eccezione del fatto che non risolve automaticamente le funzioni di accesso alle proprietà nell'oggetto . Ciò significa che se il valore di una chiave è una funzione di accesso a una proprietà, il metodo EnumerateKeys restituirà la funzione di accesso della proprietà (un oggetto IModelPropertyAccessorInterface) boxed in un oggetto IModelObject anziché chiamare automaticamente il metodo GetValue. Ciò è simile alla differenza tra GetKey e GetKeyValue.

ClearKeys

Il metodo ClearKeys rimuove tutte le chiavi e i relativi valori e metadati associati dall'istanza dell'oggetto specificato da questo oggetto. Questo metodo non ha alcun effetto sui modelli padre associati all'istanza di oggetto specifica.

GetKeyReference

Il metodo GetKeyReference cercherà una chiave del nome specificato nell'oggetto (o nella relativa catena di modelli padre) e restituirà un riferimento a tale chiave fornita da un'interfaccia IModelKeyReference boxed in un IModelObject. Tale riferimento può essere usato successivamente per ottenere o impostare il valore della chiave.

EnumerateKeyReferences

Il metodo EnumerateKeyReferences si comporta in modo simile al metodo EnumerateKeyValues, ad eccezione del fatto che restituisce riferimenti alle chiavi enumerate (dato da un'interfaccia IModelKeyReference boxed in un IModelObject) anziché il valore della chiave. Tali riferimenti possono essere usati per ottenere o impostare il valore sottostante delle chiavi.

Metodi di manipolazione dei concetti

Oltre a un oggetto modello come dizionario di tuple chiave/valore/metadati, è anche un contenitore di concetti. Un concetto è un concetto astratto che può essere eseguito su o da un oggetto . I concetti sono essenzialmente un archivio dinamico di interfacce supportate da un oggetto. Un certo numero di concetti è definito oggi dal modello di dati:

Interfaccia del concetto Descrizione
IDataModelConcept Il concetto è un modello padre. Se questo modello viene automaticamente collegato a un tipo nativo tramite una firma del tipo registrato, il metodo InitializeObject verrà chiamato automaticamente ogni volta che viene creata un'istanza di un nuovo oggetto di tale tipo.
IStringDisplayableConcept L'oggetto può essere convertito in una stringa a scopo di visualizzazione.
IIterableConcept L'oggetto è un contenitore e può essere iterato.
IIndexableConcept L'oggetto è un contenitore e può essere indicizzato (accessibile tramite accesso casuale) in una o più dimensioni.
IPreferredRuntimeTypeConcept L'oggetto comprende più informazioni sui tipi derivati rispetto al sistema di tipi sottostanti in grado di fornire e gestire le proprie conversioni da statico a tipo di runtime.
IDynamicKeyProviderConcept L'oggetto è un provider dinamico di chiavi e vuole acquisire il controllo di tutte le query chiave dal modello di dati principale. Questa interfaccia viene in genere usata come bridge a linguaggi dinamici, ad esempio JavaScript.
IDynamicConceptProviderConcept L'oggetto è un provider dinamico di concetti e vuole acquisire il controllo di tutte le query di concetto dal modello di dati di base. Questa interfaccia viene in genere usata come bridge a linguaggi dinamici, ad esempio JavaScript.

I metodi seguenti in IModelObject vengono utilizzati per modificare i concetti supportati da un oggetto .

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

Il metodo GetConcept cercherà un concetto nell'oggetto (o nella relativa catena di modelli padre) e restituirà un puntatore di interfaccia all'interfaccia del concetto. Il comportamento e i metodi in un'interfaccia di concetto sono specifici di ogni concetto. È tuttavia importante notare che molte interfacce di concetto richiedono al chiamante di passare in modo esplicito l'oggetto di contesto (o quello che si potrebbe chiamare tradizionalmente questo puntatore). È importante assicurarsi che l'oggetto contesto corretto venga passato a ogni interfaccia di concetto.

SetConcept

Il metodo SetConcept inserisce un concetto specificato nell'istanza dell'oggetto specificata dal puntatore. Se un modello padre associato all'istanza dell'oggetto specificato da questo supporta anche il concetto, l'implementazione nell'istanza eseguirà l'override di tale elemento nel modello padre.

ClearConcepts

Il metodo ClearConcepts rimuoverà tutti i concetti dall'istanza dell'oggetto specificato da questo oggetto.

Metodi dell'oggetto nativo

Anche se molti oggetti modello fanno riferimento a oggetti intrinseci (ad esempio numeri interi, stringhe) o costrutti sintetici (dizionario di tuple chiave/valore/metadati e concetti), un oggetto modello può anche fare riferimento a un costrutto nativo (ad esempio, un tipo definito dall'utente nello spazio indirizzi della destinazione di debug). L'interfaccia IModelObject dispone di una serie di metodi su di esso che accedono alle informazioni su tali oggetti nativi. Questi metodi sono:

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

Il metodo GetRawValue trova un costrutto nativo all'interno dell'oggetto specificato. Un costrutto di questo tipo può essere un campo, una classe base, un campo in una classe base, una funzione membro e così via...

EnumerateRawValues

Il metodo EnumerateRawValues enumera tutti gli elementi figlio nativi ,ad esempio campi, classi di base e così via, dell'oggetto specificato.

TryCastToRuntimeType

Il metodo TryCastToRuntimeType chiederà all'host di debug di eseguire un'analisi e determinare il tipo di runtime effettivo (ad esempio, la classe più derivata) dell'oggetto specificato. L'analisi esatta utilizzata è specifica dell'host di debug e può includere RTTI (informazioni sul tipo di runtime C++), l'esame della struttura V-Table (tabella di funzioni virtuali) dell'oggetto o qualsiasi altro mezzo che l'host può usare per determinare in modo affidabile il tipo di runtime/dinamico dal tipo statico. Se non si esegue la conversione in un tipo di runtime, questa chiamata al metodo avrà esito negativo. In questi casi, il metodo restituirà l'oggetto specificato (questo puntatore) nell'argomento di output.

GetLocation

Il metodo GetLocation restituirà la posizione dell'oggetto nativo. Anche se tale posizione è in genere un indirizzo virtuale all'interno dello spazio indirizzi della destinazione di debug, non è necessariamente così. La posizione restituita da questo metodo è una posizione astratta che può essere un indirizzo virtuale, può indicare la posizione all'interno di un registro o un registro secondario oppure può indicare un altro spazio indirizzi arbitrario definito dall'host di debug. Se il campo HostDefined dell'oggetto Location risultante è 0, indica che la posizione è effettivamente un indirizzo virtuale. È possibile recuperare tale indirizzo virtuale esaminando il campo Offset della posizione risultante. Qualsiasi valore diverso da zero del campo HostDefined indica uno spazio indirizzi alternativo in cui il campo Offset è l'offset all'interno di tale spazio indirizzi. Il significato esatto dei valori HostDefined diversi da zero è privato per l'host di debug.

GetTypeInfo

Il metodo GetTypeInfo restituirà il tipo nativo dell'oggetto specificato. Se all'oggetto non sono associate informazioni sul tipo nativo , ad esempio un intrinseco e così via, la chiamata avrà comunque esito positivo, ma restituirà Null.

GetTargetInfo

Il metodo GetTargetInfo è in effetti una combinazione dei metodi GetLocation e GetTypeInfo che restituiscono sia la posizione astratta che il tipo nativo dell'oggetto specificato.

GetRawReference

Il metodo GetRawReference trova un costrutto nativo all'interno dell'oggetto specificato e restituisce un riferimento. Un costrutto di questo tipo può essere un campo, una classe base, un campo in una classe base, una funzione membro e così via... È importante distinguere il riferimento restituito qui (un oggetto del tipo ObjectTargetObjectReference) da un riferimento al linguaggio (ad esempio, un & C++ o un riferimento di stile && ).

EnumerateRawReferences

Il metodo EnumerateRawReferences enumera i riferimenti a tutti gli elementi figlio nativi ,ad esempio campi, classi di base e così via, dell'oggetto specificato.

Metodi di estendibilità

Come descritto in precedenza, un oggetto modello si comporta in modo molto simile a un oggetto JavaScript e alla relativa catena di prototipi. Oltre all'istanza rappresentata da una determinata interfaccia IModelObject, è possibile che all'oggetto sia associato un numero arbitrario di modelli padre, ognuno dei quali può, a sua volta, avere un numero arbitrario di modelli padre collegati. Questo è il mezzo principale per l'estendibilità all'interno del modello di dati. Se una determinata proprietà o concetto non può trovarsi all'interno di una determinata istanza, viene eseguita una ricerca depth-first dell'albero degli oggetti (definito dai modelli padre) radicata nell'istanza.

I metodi seguenti modificano la catena di modelli padre associati a una determinata istanza 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

Il metodo GetNumberOfParentModels restituisce il numero di modelli padre associati all'istanza dell'oggetto specificata. I modelli padre vengono cercati la profondità delle proprietà nell'ordinamento lineare della catena di modelli padre.

GetParentModel

Il metodo GetParentModel restituisce il modello padre i-th nella catena di modelli padre dell'oggetto specificato. I modelli padre vengono cercati una proprietà o un concetto nell'ordine lineare in cui vengono aggiunti o enumerati. Il modello padre con indice i di zero viene cercato (gerarchicamente) prima del modello padre con indice i + 1.

AddParentModel

Il metodo AddParentModel aggiunge un nuovo modello padre all'oggetto specificato. Tale modello può essere aggiunto alla fine della catena di ricerca (l'argomento di override viene specificato come false) o all'inizio della catena di ricerca (l'argomento di override è specificato come true). Inoltre, ogni modello padre può facoltativamente modificare il contesto (questo puntatore semantico) per qualsiasi proprietà o concetto nell'elemento padre specificato (o chiunque nella gerarchia padre). La regolazione del contesto viene usata raramente, ma consente alcuni concetti potenti come incorporamento di oggetti, costruzione di spazi dei nomi e così via...

RemoveParentModel

RemoveParentModel rimuoverà un modello padre specificato dalla catena di ricerca padre dell'oggetto specificato.

SetContextForDataModel

Il metodo SetContextForDataModel viene utilizzato dall'implementazione di un modello di dati per inserire i dati di implementazione negli oggetti dell'istanza. Concettualmente, ogni IModelObject (chiamare questa istanza per semplicità) contiene una tabella hash di stato. La tabella hash viene indicizzata da un altro IModelObject (chiamare questo modello di dati per semplicità) che si trova nella gerarchia del modello padre dell'istanza. Il valore contenuto in questo hash è un set di informazioni sullo stato con conteggio dei riferimenti rappresentate da un'istanza IUnknown. Dopo che il modello di dati imposta questo stato nell'istanza, può archiviare dati di implementazione arbitrari che possono essere recuperati durante operazioni quali getter di proprietà.

GetContextForDataModel

Il metodo GetContextForDataModel viene usato per recuperare le informazioni sul contesto configurate con una chiamata precedente a SetContextForDataModel. In questo modo vengono recuperate le informazioni sullo stato impostate su un oggetto istanza da un modello di dati ulteriormente nella gerarchia del modello padre dell'oggetto istanza. Per altri dettagli su questo contesto/stato e sul suo significato, vedere la documentazione per SetContextForDataModel.

Tipi di oggetto core del modello di dati del debugger

Un oggetto nel modello di dati è simile al concetto di Object in .NET. Si tratta del contenitore generico in cui costruire che il modello di dati riconosce può essere sottoposto a boxing. Oltre agli oggetti nativi e agli oggetti sintetici (dinamici), esistono una serie di tipi di oggetto di base che possono essere inseriti (o boxed) nel contenitore di un IModelObject. Il contenitore in cui la maggior parte di questi valori viene inserita è una variante COM/OLE standard con una serie di restrizioni aggiuntive applicate a ciò che può contenere variant. Di seguito sono riportati i tipi di base seguenti:

  • Valori senza segno e con segno a 8 bit (VT_UI1, VT_I1)
  • Valori senza segno a 16 bit (VT_UI2, VT_UI2)
  • Valori senza segno a 32 bit (VT_UI4, VT_I4)
  • Valori senza segno a 64 bit (VT_UI8, VT_I8)
  • Valori a virgola mobile a precisione singola e doppia (VT_R4, VT_R8)
  • Stringhe (VT_BSTR)
  • Valori booleani (VT_BOOL)

Oltre a questi tipi di base, diversi oggetti core del modello di dati vengono inseriti in IModelObject definito da VT_UNKNOWN in cui l'interfaccia IUnknown archiviata è garantita per implementare un'interfaccia specifica. Questi tipi sono:

  • Funzioni di accesso alle proprietà (IModelPropertyAccessor)
  • Oggetti metodo (IModelMethod)
  • Oggetti di riferimento chiave (IModelKeyReference o IModelKeyReference2)
  • Oggetti context (IDebugModelHostContext)

Funzioni di accesso alle proprietà: IModelPropertyAccessor

Una funzione di accesso alle proprietà nel modello di dati è un'implementazione dell'interfaccia IModelPropertyAccessor boxed in un IModelObject. L'oggetto modello restituirà un tipo di ObjectPropertyAccessor quando viene eseguita una query e il valore intrinseco è un VT_UNKNOWN che è garantito che sia possibile eseguire query per IModelPropertyAccessor. In fase di elaborazione, è garantito che sia possibile eseguire il cast statico a IModelPropertyAccessor.

Una funzione di accesso alle proprietà è un modo indiretto per ottenere una chiamata al metodo per ottenere e impostare un valore di chiave nel modello di dati. Se il valore di una determinata chiave è una funzione di accesso a una proprietà, i metodi GetKeyValue e SetKeyValue noteranno automaticamente questo valore e chiameranno i metodi GetValue o SetValue sottostanti della funzione di accesso alla proprietà in base alle esigenze.

L'interfaccia IModelPropertyAccessor è definita come segue:

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

Il metodo GetValue è il getter per la funzione di accesso della proprietà. Viene chiamato ogni volta che un client desidera recuperare il valore sottostante della proprietà. Si noti che qualsiasi chiamante che ottiene direttamente una funzione di accesso di proprietà è responsabile del passaggio del nome della chiave e dell'oggetto istanza accurato (questo puntatore) al metodo GetValue della funzione di accesso della proprietà.

SetValue

Il metodo SetValue è il setter per la funzione di accesso alla proprietà. Viene chiamato ogni volta che un client desidera assegnare un valore alla proprietà sottostante. Molte proprietà sono di sola lettura. In questi casi, la chiamata al metodo SetValue restituirà E_NOTIMPL. Si noti che qualsiasi chiamante che ottiene direttamente una funzione di accesso di proprietà è responsabile del passaggio del nome della chiave e dell'oggetto istanza accurato (questo puntatore) al metodo SetValue della funzione di accesso alla proprietà.

Metodi: IModelMethod

Un metodo nel modello di dati è un'implementazione dell'interfaccia IModelMethod boxed in un IModelObject. L'oggetto modello restituirà un tipo di ObjectMethod quando viene eseguita una query e il valore intrinseco è un VT_UNKNOWN che è garantito che sia possibile eseguire query per IModelMethod. In fase di elaborazione, è garantito che sia possibile eseguire il cast statico a IModelMethod. Tutti i metodi nel modello di dati sono di natura dinamica. Accettano come input un set di 0 o più argomenti e restituiscono un singolo valore di output. Non esiste alcuna risoluzione dell'overload e nessun metadati relativi ai nomi, ai tipi o alle aspettative dei parametri.

L'interfaccia IModelMethod è definita come segue:

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

Chiamare

Il metodo Call è il modo in cui viene richiamato qualsiasi metodo definito nel modello di dati. Il chiamante è responsabile del passaggio di un oggetto istanza accurato (questo puntatore) e di un set arbitrario di argomenti. Viene restituito il risultato del metodo e dei metadati facoltativi associati a tale risultato. I metodi che non restituiscono logicamente un valore devono comunque restituire un IModelObject valido. In tal caso, IModelObject è un valore boxed senza valore. Nel caso in cui un metodo non riesca, può restituire informazioni facoltative sull'errore esteso nell'argomento di input (anche se il valore HRESULT restituito è un errore). È fondamentale che i chiamanti verifichino questo problema.

Riferimenti chiave: IModelKeyReference o IModelKeyReference2

Un riferimento alla chiave è, in sostanza, un handle per una chiave in un oggetto specifico. Un client può recuperare tali handle tramite metodi come GetKeyReference e usare l'handle in un secondo momento per ottenere o impostare il valore della chiave senza necessariamente mantenere l'oggetto originale. Questo tipo di oggetto è un'implementazione dell'interfaccia IModelKeyReference o IModelKeyReference2 boxed in un IModelObject. L'oggetto modello restituirà un tipo di ObjectKeyReference quando viene eseguita una query e quindi un valore intrinseco è un VT_UNKNOWN che è garantito che sia possibile eseguire query per IModelKeyReference. In fase di elaborazione, è garantito che sia possibile eseguire il cast statico a IModelKeyReference.

L'interfaccia di riferimento chiave è definita come segue:

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

Il metodo GetKeyName restituisce il nome della chiave a cui si riferisce questa chiave è un handle. La stringa restituita è una stringa BSTR standard e deve essere liberata tramite una chiamata a SysFreeString.

GetOriginalObject

Il metodo GetOriginalObject restituisce l'oggetto istanza da cui è stato creato il riferimento alla chiave. Si noti che la chiave può essere su un modello padre dell'oggetto istanza.

GetContextObject

Il metodo GetContextObject restituisce il contesto (questo puntatore) che verrà passato al metodo GetValue o SetValue di una funzione di accesso di una proprietà se la chiave in questione fa riferimento a una funzione di accesso di proprietà. L'oggetto di contesto restituito qui può essere o meno uguale all'oggetto originale recuperato da GetOriginalObject. Se una chiave si trova in un modello padre e a tale modello padre è associato un regolatore di contesto, l'oggetto originale è l'oggetto dell'istanza in cui è stato chiamato GetKeyReference o EnumerateKeyReferences. L'oggetto di contesto è indipendentemente dal regolatore di contesto finale tra l'oggetto originale e il modello padre contenente la chiave a cui questo riferimento chiave è un handle. Se non sono presenti regolatori di contesto, l'oggetto originale e l'oggetto di contesto sono identici.

GetKey

Il metodo GetKey su un riferimento chiave si comporta come il metodo GetKey in IModelObject. Restituisce il valore della chiave sottostante e tutti i metadati associati alla chiave. Se il valore della chiave è una funzione di accesso alle proprietà, verrà restituita la funzione di accesso alla proprietà (IModelPropertyAccessor) boxed in un IModelObject. Questo metodo non chiamerà i metodi GetValue o SetValue sottostanti nella funzione di accesso alla proprietà.

GetKeyValue

Il metodo GetKeyValue su un riferimento chiave si comporta come il metodo GetKeyValue su IModelObject. Restituisce il valore della chiave sottostante e tutti i metadati associati alla chiave. Se il valore della chiave è una funzione di accesso alla proprietà, verrà chiamato automaticamente il metodo GetValue sottostante nella funzione di accesso della proprietà.

Setkey

Il metodo SetKey in un riferimento chiave si comporta come il metodo SetKey in IModelObject. Assegnerà il valore della chiave. Se la chiave originale è una funzione di accesso alla proprietà, la funzione di accesso alla proprietà verrà sostituita. Non chiamerà il metodo SetValue sulla funzione di accesso della proprietà.

SetKeyValue

Il metodo SetKeyValue su un riferimento chiave si comporta come il metodo SetKeyValue su IModelObject. Assegnerà il valore della chiave. Se la chiave originale era una funzione di accesso alla proprietà, verrà chiamato il metodo SetValue sottostante nella funzione di accesso della proprietà anziché sostituire la funzione di accesso della proprietà stessa.

OverrideContextObject

Il metodo OverrideContextObject (presente solo in IModelKeyReference2) è un metodo avanzato usato per modificare definitivamente l'oggetto contesto che questo riferimento chiave passerà a qualsiasi metodo GetValue o SetValue della proprietà sottostante. L'oggetto passato a questo metodo verrà restituito anche da una chiamata a GetContextObject. Questo metodo può essere usato dai provider di script per replicare determinati comportamenti del linguaggio dinamico. La maggior parte dei client non deve chiamare questo metodo.

Oggetti contesto: IDebugHostContext

Gli oggetti di contesto sono BLOB opachi di informazioni associate all'host di debug (in collaborazione con il modello di dati) a ogni oggetto. Può includere elementi come il contesto del processo o lo spazio degli indirizzi provenienti dalle informazioni e così via... Un oggetto context è un'implementazione di IDebugHostContext boxed in un IModelObject. Si noti che IDebugHostContext è un'interfaccia definita dall'host. Un client non implementerà mai questa interfaccia.

Per altre informazioni sugli oggetti di contesto, vedere Interfacce host C++ del modello di dati del debugger in Interfacce C++ del modello di dati del debugger.

Gestione modelli di dati

L'interfaccia principale per la gestione modelli di dati, IDataModelManager2 (o i precedenti IDataModelManager) è definita come segue:

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

Metodi di gestione

Il set di metodi seguente viene usato dall'applicazione (ad esempio: debugger) che ospita il modello di dati.

STDMETHOD(Close)() PURE;

Close

Il metodo Close viene chiamato sulla gestione modelli di dati da un'applicazione (ad esempio: debugger) che ospita il modello di dati per avviare il processo di arresto della gestione modelli di dati. Un host del modello di dati che non è il metodo Close prima di rilasciare il relativo riferimento finale nella gestione modelli di dati può causare comportamenti non definiti, ma non limitati a perdite significative dell'infrastruttura di gestione per il modello di dati.

Creazione di oggetti /Metodi di boxing

Il set di metodi seguente viene usato per creare nuovi oggetti o per casellare i valori in un oggetto IModelObject, ovvero l'interfaccia principale del modello di dati.

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

Il metodo CreateNoValue crea un oggetto "no value", lo inserisce in un oggetto IModelObject e lo restituisce. L'oggetto modello restituito ha un tipo di ObjectNoValue.

Un oggetto "no value" ha diversi significati semantici:

  • (A seconda del linguaggio), può essere considerato l'equivalente semantico di void, Null o non definito
  • Il metodo GetValue di qualsiasi proprietà che restituisce esito positivo e un oggetto "no value" risultante indica che la proprietà specifica non ha alcun valore per l'istanza specificata e deve essere considerata come se la proprietà non esiste per tale istanza specifica.
  • I metodi del modello di dati che non dispongono di un valore restituito usano questo valore come sentinel per indicare, ad esempio un metodo deve restituire un IModelObject valido.

CreateErrorObject

Il metodo CreateErrorObject crea un "oggetto error". Il modello di dati non ha la nozione di eccezioni e flusso di eccezioni. L'errore esce da una proprietà/metodo in due modi:

  • Un singolo errore HRESULT senza informazioni di errore estese. Non sono presenti altre informazioni che possono essere fornite per l'errore o l'errore stesso è autoesplicativo dall'HRESULT restituito.
  • Un singolo errore HRESULT associato a informazioni di errore estese. Le informazioni sull'errore estese sono un oggetto di errore restituito nell'argomento di output della proprietà/metodo.

CreateTypedObject

Il metodo CreateTypedObject è il metodo che consente a un client di creare una rappresentazione di un oggetto nativo/linguistico nello spazio indirizzi di una destinazione di debug. Se il tipo dell'oggetto appena creato (come indicato dall'argomento objectType) corrisponde a una o più firme di tipo registrate con gestione modelli di dati come visualizzatori canonici o estensioni, tali modelli di dati corrispondenti verranno collegati automaticamente all'oggetto istanza creata prima che venga restituito al chiamante.

CreateTypedObjectReference

Il metodo CreateTypedObjectReference è semanticamente simile al metodo CreateTypedObject, ad eccezione del fatto che crea un riferimento al costrutto nativo/linguistico sottostante. Il riferimento creato è un oggetto che ha un tipo di ObjectTargetObjectReference. Non è un riferimento nativo perché il linguaggio sottostante potrebbe supportare (ad esempio, un & C++ o &&). È completamente possibile avere un oggetto ObjectTargetObjectReference a un riferimento C++. Un oggetto di tipo ObjectTargetObjectReference può essere convertito nel valore sottostante tramite l'uso del metodo Dereference in IModelObject. Il riferimento può anche essere passato all'analizzatore di espressioni dell'host sottostante per assegnare nuovamente il valore in un linguaggio appropriato.

CreateSyntheticObject

Il metodo CreateSyntheticObject crea un oggetto modello di dati vuoto, ovvero un dizionario di tuple chiave/valore/metadati e concetti. Al momento della creazione, non sono presenti chiavi né concetti sull'oggetto. È uno slate pulito per il chiamante da usare.

CreateDataModelObject

Il metodo CreateDataModelObject è un semplice wrapper helper per creare oggetti che sono modelli di dati, ovvero oggetti che verranno collegati come modelli padre ad altri oggetti. Tutti questi oggetti devono supportare il concetto di modello di dati tramite IDataModelConcept. Questo metodo crea un nuovo oggetto sintetico vuoto senza contesto esplicito e aggiunge l'IDataModelConcept inpassed come implementazione dell'oggetto appena creato del concetto di modello di dati. Questa operazione può essere eseguita in modo analogo con le chiamate a CreateSyntheticObject e SetConcept.

CreateIntrinsicObject

Il metodo CreateIntrinsicObject è il metodo che riquadri i valori intrinseci in IModelObject. Il chiamante inserisce il valore in UN VALORE COM VARIANT e chiama questo metodo. Gestione modelli di dati restituisce un oggetto IModelObject che rappresenta l'oggetto. Si noti che questo metodo viene usato anche per casellare i tipi di base IUnknown fondamentali: funzioni di accesso delle proprietà, metodi, contesti e così via... In questi casi, il metodo objectKind indica quale tipo di costrutto basato su IUnknown rappresenta l'oggetto e il campo punkVal della variante passata è il tipo derivato IUnknown. Il tipo deve essere sottoposto a cast statico all'interfaccia del modello appropriata(ad esempio: IModelPropertyAccessor, IModelMethod, IDebugHostContext e così via...) nel processo. I tipi VARIANT supportati da questo metodo sono 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 (per un set specializzato di tipi derivati IUnknown, come indicato dall'enumerazione ModelObjectKind.

CreateTypedIntrinsicObject

Il metodo CreateTypedintrinsicObject è simile al metodo CreateIntrinsicObject, ad eccezione del fatto che consente l'associazione di un tipo nativo/linguistico ai dati e portato insieme al valore boxed. Ciò consente al modello di dati di rappresentare costrutti come i tipi di enumerazione nativa (che sono semplicemente VT_UI* o VT_I* valori). I tipi di puntatore vengono creati anche con questo metodo. Un puntatore nativo nel modello di dati è una quantità di 64 bit estesa zero che rappresenta un offset nello spazio indirizzi virtuale della destinazione di debug. Viene casellato all'interno di un VT_UI8 e viene creato con questo metodo e un tipo che indica un puntatore nativo/linguistico.

CreateMetadataStore

Il metodo CreateMetadataStore crea un archivio chiavi, un contenitore semplificato di tuple chiave/valore/metadati, che viene usato per contenere i metadati che possono essere associati alle proprietà e a un'ampia gamma di altri valori. Un archivio metadati può avere un singolo padre (che a sua volta può avere un singolo padre). Se una chiave di metadati specificata non si trova in un determinato archivio, i relativi genitori vengono controllati. La maggior parte degli archivi di metadati non dispone di genitori. Tuttavia, offre un modo per condividere facilmente i metadati comuni.

CreateTypedIntrinsicObjectEx

Il metodo CreateTypedIntrinsicObjectEx è semanticamente simile al metodo CreateTypedIntrinsicObject. L'unica differenza tra i due è che questo metodo consente al chiamante di specificare il contesto in cui i dati intrinseci sono validi. Se non viene passato alcun contesto, i dati vengono considerati validi in qualsiasi contesto ereditato dall'argomento di tipo (come si comporta CreateTypedIntrinsicObject). Ciò consente la creazione di valori di puntatore tipizzati nella destinazione di debug che richiedono un contesto più specifico di quanto possa essere ereditato dal tipo.

Estendibilità/metodi di registrazione Il set di metodi seguente gestisce il meccanismo di estendibilità del modello di dati, consentendo a un client di estendere o registrare modelli esistenti o chiedere al modello di dati di collegare automaticamente un determinato modello padre ai tipi nativi che corrispondono a un determinato criterio.

    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

Il metodo GetModelForTypeSignature restituisce il modello di dati registrato in base a una determinata firma di tipo tramite una chiamata precedente al metodo RegisterModelForTypeSignature. Il modello di dati restituito da questo metodo è considerato il visualizzatore canonico per qualsiasi tipo che corrisponde alla firma del tipo passato. Come visualizzatore canonico, tale modello di dati assume la visualizzazione del tipo. Per impostazione predefinita, i motori di visualizzazione nasconderanno costrutti nativi/linguistici dell'oggetto a favore della visualizzazione dell'oggetto presentato dal modello di dati.

GetModelForType

Il metodo GetModelForType restituisce il modello di dati che è il visualizzatore canonico per un'istanza di tipo specificata. In effetti, questo metodo trova la firma del tipo corrispondente migliore registrata con una chiamata precedente al metodo RegisterModelForTypeSignature e restituisce il modello di dati associato.

RegisterModelForTypeSignature

Il metodo RegisterModelForTypeSignature è il metodo primario usato da un chiamante per registrare un visualizzatore canonico per un determinato tipo (o set di tipi). Un visualizzatore canonico è un modello di dati che, in effetti, accetta la visualizzazione di un determinato tipo (o set di tipi). Anziché la visualizzazione nativa/lingua del tipo visualizzata in qualsiasi interfaccia utente del debugger, viene visualizzata la visualizzazione del tipo come presentato dal modello di dati registrato (insieme a un mezzo per tornare alla visualizzazione nativa/lingua per un utente che lo desidera).

UnregisterModelForTypeSignature

Il metodo UnregisterModelForTypeSignature annulla una chiamata precedente al metodo RegisterModelForTypeSignature. Questo metodo può rimuovere un determinato modello di dati come visualizzatore canonico per i tipi che corrispondono a una determinata firma di tipo oppure può rimuovere un determinato modello di dati come visualizzatore canonico per ogni firma di tipo in cui è registrato il modello di dati.

RegisterExtensionForTypeSignature

Il metodo RegisterExtensionForTypeSignature è simile al metodo RegisterModelForTypeSignature con una differenza chiave. Il modello di dati passato a questo metodo non è il visualizzatore canonico per qualsiasi tipo e non assumerà la visualizzazione della visualizzazione nativa/lingua di tale tipo. Il modello di dati passato a questo metodo verrà aggiunto automaticamente come elemento padre a qualsiasi tipo concreto corrispondente alla firma del tipo specificato. A differenza del metodo RegisterModelForTypeSignature, non esiste alcun limite per firme di tipo identiche o ambigue registrate come estensioni a un determinato tipo (o set di tipi). Ogni estensione la cui firma di tipo corrisponde a un'istanza di tipo concreto specifica causerà l'associazione automatica del modello di dati registrato tramite questo metodo agli oggetti appena creati come modelli padre. In effetti, consente a un numero arbitrario di client di estendere un tipo (o un set di tipi) con nuovi campi o funzionalità.

UnregisterExtensionForTypeSignature

Il metodo UnregisterExtensionForTypeSignature annulla una chiamata precedente a RegisterExtensionForTypeSignature. Annulla la registrazione di un particolare modello di dati come estensione per una determinata firma di tipo o come estensione per tutte le firme di tipo a cui è stato registrato il modello di dati.

GetRootNamespace

Il metodo GetRootNamespace restituisce lo spazio dei nomi radice del modello di dati. Si tratta di un oggetto che il modello di dati gestisce e in cui l'host di debug inserisce determinati oggetti.

RegisterNamedModel

Il metodo RegisterNamedModel registra un determinato modello di dati con un nome noto in modo che possa essere trovato dai client che desiderano estenderlo. Questo è lo scopo principale dell'API: pubblicare un modello di dati come elemento che può essere esteso recuperando il modello registrato in questo nome noto e aggiungendo un modello padre.

Annullare la registrazione diNamedModel

Il metodo UnregisterNamedModel annulla una chiamata precedente a RegisterNamedModel. Rimuove l'associazione tra un modello di dati e un nome in cui può essere cercata.

AcquireNamedModel

Un chiamante che desidera estendere un modello di dati registrato in un determinato nome chiama il metodo AcquireNamedModel per recuperare l'oggetto per il modello di dati che desidera estendere. Questo metodo restituirà qualsiasi modello di dati registrato tramite una chiamata precedente al metodo RegisterNamedModel. Come scopo principale del metodo AcquireNamedModel è estendere il modello, questo metodo ha un comportamento speciale se non è ancora stato registrato alcun modello con il nome specificato. Se non è ancora stato registrato alcun modello con il nome specificato, viene creato un oggetto stub, registrato temporaneamente con il nome specificato e restituito al chiamante. Quando il modello di dati reale viene registrato tramite una chiamata al metodo RegisterNamedModel, tutte le modifiche apportate all'oggetto stub sono, in effetti, apportate al modello reale. In questo modo vengono rimossi molti problemi di dipendenza dell'ordine di carico dai componenti che si estendono l'uno all'altro.

Metodi helper

I metodi seguenti sono metodi helper generali che consentono di eseguire operazioni complesse sugli oggetti nel modello di dati. Anche se è possibile eseguire queste azioni tramite altri metodi sul modello di dati o sui relativi oggetti, questi metodi pratici semplificano notevolmente:

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

AcquireSubNamespace

Il metodo AcquireSubNamespace consente di costruire qualcosa che potrebbe essere più tradizionalmente simile a uno spazio dei nomi del linguaggio rispetto a un nuovo oggetto in un linguaggio dinamico. Se, ad esempio, un chiamante vuole categorizzare le proprietà in un oggetto process per rendere l'oggetto processo più organizzato e le proprietà più facili da individuare, un metodo di questa operazione consiste nel creare un sotto-oggetto per ogni categoria nell'oggetto process e posizionare tali proprietà all'interno di tale oggetto.

Vedere anche

Questo argomento fa parte di una serie che descrive le interfacce accessibili da C++, come usarle per creare un'estensione del debugger basata su C++ e come usare altri costrutti di modelli di dati (ad esempio JavaScript o NatVis) da un'estensione del modello di dati C++.

Panoramica del modello di dati del debugger C++

Interfacce C++ del modello di dati del debugger

Interfacce aggiuntive del modello di dati del debugger C++

Concetti relativi al modello di dati del debugger C++

Script C++ del modello di dati del debugger