Concetti relativi al modello di dati del debugger C++
Questo argomento descrive i concetti del modello di dati C++ del debugger.
Concetti relativi al modello di dati
Gli oggetti sintetici nel modello di dati sono in effetti due elementi:
- Dizionario di tuple chiave/valore/metadati.
- Set di concetti (interfacce) supportati dal modello di dati. I concetti sono interfacce implementate da un client (anziché dal modello di dati) per fornire un set specificato di comportamento semantico. Il set di concetti attualmente supportato è elencato qui.
Interfaccia concept | Descrizione |
---|---|
IDataModelConcept | Il concetto è un modello padre. Se questo modello viene collegato automaticamente a un tipo nativo tramite una firma di 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 di più sui tipi derivati rispetto al sistema di tipi sottostante in grado di fornire e di gestire le proprie conversioni dal tipo statico al tipo di runtime. |
IDynamicKeyProviderConcept | L'oggetto è un provider dinamico di chiavi e vuole assumere tutte le query chiave dal modello di dati di base. Questa interfaccia viene in genere usata come bridge per linguaggi dinamici, ad esempio JavaScript. |
IDynamicConceptProviderConcept | L'oggetto è un provider dinamico di concetti e vuole assumere tutte le query di concetto dal modello di dati di base. Questa interfaccia viene in genere usata come bridge per linguaggi dinamici, ad esempio JavaScript. |
Concetto di modello di dati: IDataModelConcept
Qualsiasi oggetto modello collegato a un altro oggetto modello come modello padre deve supportare direttamente il concetto di modello di dati. Il concetto di modello di dati richiede il supporto di un'interfaccia, IDataModelConcept definita come segue.
DECLARE_INTERFACE_(IDataModelConcept, IUnknown)
{
STDMETHOD(InitializeObject)(_In_ IModelObject* modelObject, _In_opt_ IDebugHostTypeSignature* matchingTypeSignature, _In_opt_ IDebugHostSymbolEnumerator* wildcardMatches) PURE;
STDMETHOD(GetName)(_Out_ BSTR* modelName) PURE;
}
Un modello di dati può essere registrato come visualizzatore canonico o come estensione per un determinato tipo nativo tramite i metodi RegisterModelForTypeSignature o RegisterExtensionForTypeSignature di Data Model Manager. Quando un modello viene registrato tramite uno di questi metodi, il modello di dati viene automaticamente associato come modello padre a qualsiasi oggetto nativo il cui tipo corrisponde alla firma passata nella registrazione. Nel punto in cui viene eseguito automaticamente l'allegato, viene chiamato il metodo InitializeObject nel modello di dati. Viene passato l'oggetto istanza, la firma del tipo che ha causato l'allegato e un enumeratore che produce le istanze del tipo (in ordine lineare) che corrispondono a qualsiasi carattere jolly nella firma del tipo. L'implementazione del modello di dati può usare questa chiamata al metodo per inizializzare tutte le cache necessarie.
Se un determinato modello di dati viene registrato con un nome predefinito tramite il metodo RegisterNamedModel, l'interfaccia IDataModelConcept del modello di dati registrato deve restituire tale nome da questo metodo. Si noti che è perfettamente legittimo che un modello venga registrato con più nomi (il valore predefinito o migliore dovrebbe essere restituito qui). Un modello può essere completamente senza nome (purché non sia registrato con un nome). In tali circostanze, il metodo GetName deve restituire E_NOTIMPL.
Concetto visualizzabile di stringhe: IStringDisplayableConcept
Un oggetto che desidera fornire una conversione di stringa a scopo di visualizzazione può implementare il concetto visualizzabile di stringa tramite l'implementazione dell'interfaccia IStringDisplayableConcept. L'interfaccia viene definita come segue:
DECLARE_INTERFACE_(IStringDisplayableConcept, IUnknown)
{
STDMETHOD(ToDisplayString)(_In_ IModelObject* contextObject, _In_opt_ IKeyStore* metadata, _Out_ BSTR* displayString) PURE;
}
Il metodo ToDisplayString viene chiamato ogni volta che un client desidera convertire un oggetto in una stringa da visualizzare (nella console, nell'interfaccia utente e così via). Tale conversione di stringhe non deve essere utilizzata per la base di ulteriori modifiche a livello di codice. La conversione di stringa stessa può essere profondamente influenzata dai metadati passati alla chiamata. Una conversione di stringa deve eseguire ogni tentativo di rispettare le chiavi PreferredRadix e PreferredFormat.
Concetto iterabile: IIterableConcept e IModelIterator
Un oggetto che è un contenitore di altri oggetti e vuole esprimere la possibilità di scorrere tali oggetti contenuti può supportare il concetto iterabile da un'implementazione delle interfacce IIterableConcept e IModelIterator. Esiste una relazione molto importante tra il supporto del concetto iterabile e il supporto del concetto indicizzabile. Un oggetto che supporta l'accesso casuale agli oggetti contenuti può supportare il concetto indicizzabile oltre al concetto iterabile. In questo caso, gli elementi iterati devono produrre anche un indice predefinito che, quando passato al concetto indicizzabile, fa riferimento allo stesso oggetto. Un errore di soddisfare questo valore invariante comporterà un comportamento non definito nell'host di debug.
IIterableConcept è definito come segue:
DECLARE_INTERFACE_(IIterableConcept, IUnknown)
{
STDMETHOD(GetDefaultIndexDimensionality)(_In_ IModelObject* contextObject, _Out_ ULONG64* dimensionality) PURE;
STDMETHOD(GetIterator)(_In_ IModelObject* contextObject, _Out_ IModelIterator** iterator) PURE;
}
Il concetto di IModelIterator è definito come segue:
DECLARE_INTERFACE_(IModelIterator, IUnknown)
{
STDMETHOD(Reset)() PURE;
STDMETHOD(GetNext)(_COM_Errorptr_ IModelObject** object, _In_ ULONG64 dimensions, _Out_writes_opt_(dimensions) IModelObject** indexers, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
}
GetDefaultIndexDimensionality di IIterableConcept
Il metodo GetDefaultIndexDimensionality restituisce il numero di dimensioni all'indice predefinito. Se un oggetto non è indicizzabile, questo metodo deve restituire 0 e avere esito positivo (S_OK). Qualsiasi oggetto che restituisce un valore diverso da zero da questo metodo dichiara il supporto per un contratto di protocollo che indica:
- L'oggetto supporta il concetto indicizzabile tramite il supporto di IIndexableConcept
- Il metodo GetNext dell'oggetto IModelIterator restituito dal metodo GetIterator del concetto iterabile restituirà un indice predefinito univoco per ogni elemento prodotto. Tale indice avrà il numero di dimensioni come indicato qui.
- Il passaggio degli indici restituiti dal metodo GetNext di IModelIterator al metodo GetAt sul concetto indicizzatore (IIndexableConcept) farà riferimento allo stesso oggetto prodotto da GetNext. Viene restituito lo stesso valore.
GetIterator di IIterableConcept
Il metodo GetIterator sul concetto iterabile restituisce un'interfaccia iteratore che può essere usata per scorrere l'oggetto. L'iteratore restituito deve ricordare l'oggetto contesto passato al metodo GetIterator. Non verrà passato ai metodi sull'iteratore stesso.
Reimpostazione di IModelIterator
Il metodo Reset su un iteratore restituito dal concetto iterabile ripristina la posizione dell'iteratore in cui si trovava al momento della creazione dell'iteratore (prima del primo elemento). Sebbene sia vivamente consigliabile che l'iteratore supporti il metodo Reset, non è obbligatorio. Un iteratore può essere l'equivalente di un iteratore di input C++ e consentire solo un singolo passaggio di iterazione in avanti. In tal caso, il metodo Reset potrebbe non riuscire con E_NOTIMPL.
GetNext di IModelIterator
Il metodo GetNext sposta l'iteratore in avanti e recupera l'elemento iterato successivo. Se l'oggetto è indicizzato oltre a essere iterabile e questo è indicato dall'argomento GetDefaultIndexDimensionality che restituisce un valore diverso da zero, questo metodo può facoltativamente restituire gli indici predefiniti per tornare al valore prodotto dall'indicizzatore. Si noti che un chiamante può scegliere di passare 0/nullptr e non recuperare indici. È considerato illegale per il chiamante richiedere indici parziali (ad esempio, minore del numero prodotto da GetDefaultIndexDimensionality).
Se l'iteratore è stato spostato in avanti correttamente ma si è verificato un errore durante la lettura del valore dell'elemento iterato, il metodo potrebbe restituire un errore E riempire "oggetto" con un oggetto error. Alla fine dell'iterazione degli elementi contenuti, l'iteratore restituirà E_BOUNDS dal metodo GetNext. Qualsiasi chiamata successiva (a meno che non sia stata eseguita una chiamata di reimpostazione) restituirà anche E_BOUNDS.
Concetto indicizzatore: IIndexableConcept
Un oggetto che desidera fornire l'accesso casuale a un set di contenuti può supportare il concetto indicizzabile tramite il supporto dell'interfaccia IIndexableConcept. La maggior parte degli oggetti indicizzabili sarà iterabile anche tramite il supporto del concetto iterabile. Questo non è tuttavia obbligatorio. Se supportato, esiste una relazione importante tra l'iteratore e l'indicizzatore. L'iteratore deve supportare GetDefaultIndexDimensionality, restituire un valore diverso da zero da tale metodo e supportare il contratto documentato. L'interfaccia del concetto di indicizzatore è definita come segue:
DECLARE_INTERFACE_(IIndexableConcept, IUnknown)
{
STDMETHOD(GetDimensionality)(_In_ IModelObject* contextObject, _Out_ ULONG64* dimensionality) PURE;
STDMETHOD(GetAt)(_In_ IModelObject* contextObject, _In_ ULONG64 indexerCount, _In_reads_(indexerCount) IModelObject** indexers, _COM_Errorptr_ IModelObject** object, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
STDMETHOD(SetAt)(_In_ IModelObject* contextObject, _In_ ULONG64 indexerCount, _In_reads_(indexerCount) IModelObject** indexers, _In_ IModelObject *value) PURE;
}
Di seguito è riportato un esempio di utilizzo dell'indicizzatore (e della relativa interazione con l'iteratore). In questo esempio viene eseguito l'iterazione del contenuto di un contenitore indicizzatore e viene usato l'indicizzatore per tornare al valore appena restituito. Sebbene l'operazione sia funzionalmente inutile come scritta, dimostra come interagiscono queste interfacce. Si noti che l'esempio seguente non gestisce l'errore di allocazione della memoria. Si presuppone che venga generata una nuova eccezione (che potrebbe essere un presupposto non appropriato a seconda dell'ambiente in cui esiste il codice: i metodi COM del modello di dati non possono avere eccezioni C++):
ComPtr<IModelObject> spObject;
//
// Assume we have gotten some object in spObject that is iterable (e.g.: an object which represents a std::vector<SOMESTRUCT>)
//
ComPtr<IIterableConcept> spIterable;
ComPtr<IIndexableConcept> spIndexer;
if (SUCCEEDED(spObject->GetConcept(__uuidof(IIterableConcept), &spIterable, nullptr)) &&
SUCCEEDED(spObject->GetConcept(__uuidof(IIndexableConcept), &spIndexable, nullptr)))
{
ComPtr<IModelIterator> spIterator;
//
// Determine how many dimensions the default indexer is and allocate the requisite buffer.
//
ULONG64 dimensions;
if (SUCCEEDED(spIterable->GetDefaultIndexDimensionality(spObject.Get(), &dimensions)) && dimensions > 0 &&
SUCCEEDED(spIterable->GetIterator(spObject.Get(), &spIterator)))
{
std::unique_ptr<ComPtr<IModelObject>[]> spIndexers(new ComPtr<IModelObject>[dimensions]);
//
// We have an iterator. Error codes have semantic meaning here. E_BOUNDS indicates the end of iteration. E_ABORT indicates that
// the debugger host or application is trying to abort whatever operation is occurring. Anything else indicates
// some other error (e.g.: memory read failure) where the iterator MIGHT still produce values.
//
for(;;)
{
ComPtr<IModelObject> spContainedStruct;
ComPtr<IKeyStore> spContainedMetadata;
//
// When we fetch the value from the iterator, it will pass back the default indices.
//
HRESULT hr = spIterable->GetNext(&spContainedStruct, dimensions, reinterpret_cast<IModelObject **>(spIndexers.get()), &spContainedMetadata);
if (hr == E_BOUNDS || hr == E_ABORT)
{
break;
}
if (FAILED(hr))
{
//
// Decide how to deal with failure to fetch an element. Note that spContainedStruct *MAY* contain an error object
// which has detailed information about why the failure occurred (e.g.: failure to read memory at address X).
//
}
//
// Use the indexer to get back to the same value. We already have them, so there isn't much functional point to this. It simply
// highlights the interplay between iterator and indexer.
//
ComPtr<IModelObject> spIndexedStruct;
ComPtr<IKeyStore> spIndexedMetadata;
if (SUCCEEDED(spIndexer->GetAt(spObject.Get(), dimensions, reinterpret_cast<IModelObject **>(spIndexers.get()), &spIndexedStruct, &spIndexedMetadata)))
{
//
// spContainedStruct and spIndexedStruct refer to the same object. They may not have interface equality.
// spContainedMetadata and spIndexedMetadata refer to the same metadata store with the same contents. They may not have interface equality.
//
}
}
}
}
Il metodo GetDimensionality restituisce il numero di dimensioni in cui è indicizzato l'oggetto. Si noti che se l'oggetto è iterabile e indicizzabile, l'implementazione di GetDefaultIndexDimensionality deve essere d'accordo con l'implementazione di GetDimensionality per quanto riguarda il numero di dimensioni di cui dispone l'indicizzatore.
Il metodo GetAt recupera il valore in corrispondenza di un particolare indice N-dimensionale dall'interno dell'oggetto indicizzato. Un indicizzatore di N dimensioni in cui N è il valore restituito da GetDimensionality deve essere supportato. Si noti che un oggetto può essere indicizzato in domini diversi in base a tipi diversi , ad esempio indicizzabile tramite ordinali e stringhe. Se l'indice non è compreso nell'intervallo (o non è stato possibile accedervi), il metodo restituirà un errore; In questi casi, tuttavia, l'oggetto di output può comunque essere impostato su un oggetto errore.
Il metodo SetAt tenta di impostare il valore in corrispondenza di un particolare indice N-dimensionale dall'interno dell'oggetto indicizzato. Un indicizzatore di N dimensioni in cui N è il valore restituito da GetDimensionality deve essere supportato. Si noti che un oggetto può essere indicizzato in domini diversi in base a tipi diversi , ad esempio indicizzabile tramite ordinali e stringhe. Alcuni indicizzatori sono di sola lettura. In questi casi, E_NOTIMPL verrà restituito da qualsiasi chiamata al metodo SetAt.
Concetto di tipo di runtime preferito: IPreferredRuntimeTypeConcept
È possibile eseguire una query su un host di debug per tentare di determinare il tipo di runtime reale di un oggetto da un tipo statico trovato nelle informazioni simbolica. Questa conversione può essere basata su informazioni completamente accurate (ad esempio: C++ RTTI) o può essere basata su euristica avanzata, ad esempio la forma di qualsiasi tabella di funzioni virtuali all'interno dell'oggetto. Alcuni oggetti, tuttavia, non possono essere convertiti da un tipo statico a un tipo di runtime perché non rientrano nell'euristica dell'host di debug( ad esempio, non hanno tabelle di funzioni virtuali o RTTI). In questi casi, un modello di dati per un oggetto può scegliere di eseguire l'override del comportamento predefinito e dichiarare che conosce meglio il "tipo di runtime" di un oggetto rispetto all'host di debug in grado di comprendere. Questa operazione viene eseguita tramite il concetto di tipo di runtime preferito e il supporto dell'interfaccia IPreferredRuntimeTypeConcept.
L'interfaccia IPreferredRuntimeTypeConcept viene dichiarata come segue:
DECLARE_INTERFACE_(IPreferredRuntimeTypeConcept, IUnknown)
{
STDMETHOD(CastToPreferredRuntimeType)(_In_ IModelObject* contextObject, _COM_Errorptr_ IModelObject** object) PURE;
}
Il metodo CastToPreferredRuntimeType viene chiamato ogni volta che un client desidera tentare di eseguire la conversione da un'istanza di tipo statico al tipo di runtime di tale istanza. Se l'oggetto in questione supporta (tramite uno dei modelli padre associati) il concetto di tipo di runtime preferito, questo metodo verrà chiamato per eseguire la conversione. Questo metodo può restituire l'oggetto originale (non è disponibile alcuna conversione o non è stato possibile analizzarlo), restituire una nuova istanza del tipo di runtime, non riuscire per motivi non semantici (ad esempio, memoria insufficiente) o restituire E_NOT_edizione Standard T. Il codice di errore E_NOT_edizione Standard T è un codice di errore molto speciale che indica al modello di dati che l'implementazione non vuole eseguire l'override del comportamento predefinito e che il modello di dati deve eseguire il fallback a qualsiasi analisi eseguita dall'host di debug (ad esempio, analisi RTTI, esame della forma delle tabelle delle funzioni virtuali, ecc.
Concetti relativi ai provider dinamici: IDynamicKeyProviderConcept e IDynamicConceptProviderConcept
Anche se il modello di dati stesso gestisce normalmente la gestione delle chiavi e dei concetti per gli oggetti, esistono momenti in cui tale nozione è minore dell'ideale. In particolare, quando un client vuole creare un ponte tra il modello di dati e qualcos'altro che sia realmente dinamico (ad esempio, JavaScript), può essere utile assumere la gestione delle chiavi e dei concetti dall'implementazione nel modello di dati. Poiché il modello di dati di base è l'unica implementazione di IModelObject, questa operazione viene invece eseguita tramite una combinazione di due concetti: il concetto di provider di chiavi dinamiche e il concetto di provider di concetti dinamici. Anche se sarebbe tipico implementare entrambi o nessuno dei due, non esiste alcun requisito per tale.
Se entrambi vengono implementati, è necessario aggiungere il concetto di provider di chiavi dinamiche prima del concetto di provider di concetti dinamici. Entrambi questi concetti sono speciali. Capovolgono effettivamente un interruttore sull'oggetto che lo modifica da "gestito in modo statico" a "gestito in modo dinamico". Questi concetti possono essere impostati solo se non sono presenti chiavi/concetti gestiti dal modello di dati nell'oggetto . Dopo aver aggiunto questi concetti a un oggetto, l'azione di questa operazione è irrevocabile.
Esiste una differenza semantica aggiuntiva rispetto all'estendibilità tra un IModelObject che è un provider di concetti dinamici e uno che non lo è. Questi concetti sono progettati per consentire ai client di creare bridge tra il modello di dati e i sistemi del linguaggio dinamico, ad esempio JavaScript. Il modello di dati ha un concetto di estendibilità leggermente diverso da sistemi come JavaScript, in quanto esiste un albero di modelli padre anziché una catena lineare come la catena di prototipi JavaScript. Per consentire una migliore relazione con tali sistemi, un IModelObject che è un provider di concetti dinamici ha un singolo elemento padre del modello di dati. Tale singolo elemento padre del modello di dati è un normale IModelObject che può avere un numero arbitrario di modelli padre, come in genere per il modello di dati. Tutte le richieste al provider di concetti dinamici per aggiungere o rimuovere elementi padre vengono reindirizzate automaticamente al singolo elemento padre. Dal punto di vista di un outsider, sembra che il provider di concetti dinamici abbia una normale catena di stili albero dei modelli padre. L'implementatore del concetto di provider di concetti dinamici è l'unico oggetto (al di fuori del modello di dati di base) che riconosce il singolo elemento padre intermedio. Tale singolo elemento padre può essere collegato al sistema del linguaggio dinamico per fornire un bridge (ad esempio, inserito nella catena di prototipi JavaScript).
Il concetto di provider di chiavi dinamiche è definito come segue:
DECLARE_INTERFACE_(IDynamicKeyProviderConcept, IUnknown)
{
STDMETHOD(GetKey)(_In_ IModelObject *contextObject, _In_ PCWSTR key, _COM_Outptr_opt_result_maybenull_ IModelObject** keyValue, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata, _Out_opt_ bool *hasKey) PURE;
STDMETHOD(SetKey)(_In_ IModelObject *contextObject, _In_ PCWSTR key, _In_ IModelObject *keyValue, _In_ IKeyStore *metadata) PURE;
STDMETHOD(EnumerateKeys)(_In_ IModelObject *contextObject, _COM_Outptr_ IKeyEnumerator **ppEnumerator) PURE;
}
Il concetto di provider di concetti dinamici è definito come segue:
DECLARE_INTERFACE_(IDynamicConceptProviderConcept, IUnknown)
{
STDMETHOD(GetConcept)(_In_ IModelObject *contextObject, _In_ REFIID conceptId, _COM_Outptr_result_maybenull_ IUnknown **conceptInterface, _COM_Outptr_opt_result_maybenull_ IKeyStore **conceptMetadata, _Out_ bool *hasConcept) PURE;
STDMETHOD(SetConcept)(_In_ IModelObject *contextObject, _In_ REFIID conceptId, _In_ IUnknown *conceptInterface, _In_opt_ IKeyStore *conceptMetadata) PURE;
STDMETHOD(NotifyParent)(_In_ IModelObject *parentModel) PURE;
STDMETHOD(NotifyParentChange)(_In_ IModelObject *parentModel) PURE;
STDMETHOD(NotifyDestruct)() PURE;
}
GetKeyProviderConcept di IDynamicKey
Il metodo GetKey in un provider di chiavi dinamiche è in gran parte un override del metodo GetKey in IModelObject. Il provider di chiavi dinamiche deve restituire il valore della chiave e tutti i metadati associati a tale chiave. Nel caso in cui la chiave non sia presente (ma non si verifica alcun altro errore), il provider deve restituire false nel parametro hasKey e avere esito positivo con S_OK. L'esito negativo di questa chiamata è considerato un errore durante il recupero di una chiave e interromperà in modo esplicito la ricerca della chiave tramite la catena di modelli padre. La restituzione di false in hasKey e l'esito positivo continuerà la ricerca della chiave. Si noti che è perfettamente valido per GetKey per restituire una funzione di accesso alle proprietà boxed come chiave. Questo metodo sarebbe semanticamente identico al metodo GetKey in IModelObject che restituisce una funzione di accesso alle proprietà.
SetKeyProviderConcept di IDynamicKey
Il metodo SetKey in un provider di chiavi dinamiche è in effetti un override del metodo SetKey in IModelObject. In questo modo viene impostata una chiave nel provider dinamico. È in effetti la creazione di una nuova proprietà nel provider. Si noti che un provider che non supporta alcuna nozione di qualcosa come la creazione di proprietà expando deve restituire E_NOTIMPL qui.
EnumerateKeyProviderConcept di IDynamicKeyProvider
Il metodo EnumerateKeys in un provider di chiavi dinamiche è in effetti un override del metodo EnumerateKeys in IModelObject. Vengono enumerate tutte le chiavi nel provider dinamico. L'enumeratore restituito presenta diverse restrizioni che devono essere rispettate dall'implementazione:
- Deve comportarsi come chiamata a EnumerateKeys e non EnumerateKeyValues o EnumerateKeyReferences. Deve restituire i valori di chiave che non risolve le funzioni di accesso alle proprietà sottostanti (se tale concetto esiste nel provider).
- Dal punto di vista di un singolo provider di chiavi dinamiche, è illegale enumerare più chiavi con lo stesso nome che sono chiavi fisicamente distinte. Ciò può verificarsi su provider diversi collegati tramite la catena di modelli padre, ma non può verificarsi dal punto di vista di un singolo provider.
GetConceptProviderConcept di IDynamicConcept
Il metodo GetConcept in un provider di concetti dinamici è in effetti un override del metodo GetConcept in IModelObject. Il provider di concetti dinamici deve restituire un'interfaccia per il concetto sottoposto a query, se esistente, nonché i metadati associati a tale concetto. Se il concetto non esiste nel provider, tale valore deve essere indicato tramite un valore false restituito nell'argomento hasConcept e una restituzione riuscita. L'errore di questo metodo non riesce a recuperare il concetto e interromperà in modo esplicito la ricerca del concetto. La restituzione di false per hasConcept e un codice con esito positivo continuerà la ricerca del concetto tramite l'albero del modello padre.
SetConceptProviderConcept di IDynamicConcept
Il metodo SetConcept in un provider di concetti dinamici è in effetti un override del metodo SetConcept in IModelObject. Il provider dinamico assegnerà il concetto. Ciò può rendere l'oggetto iterabile, indicizzabile, convertibile in stringhe e così via... Si noti che un provider che non consente la creazione di concetti su di esso deve restituire E_NOPTIMPL qui.
NotifyParent di IDynamicConceptProviderConcept
La chiamata NotifyParent su un provider di concetti dinamici viene usata dal modello di dati di base per informare il provider dinamico del modello padre singolo creato per consentire il bridging del paradigma "più modelli padre" del modello di dati in linguaggi più dinamici. Qualsiasi modifica del modello padre singolo causerà ulteriori notifiche al provider dinamico. Si noti che questo callback viene eseguito immediatamente dopo l'assegnazione del concetto di provider di concetti dinamici.
NotifyParentChange di IDynamicConceptProviderConcept
Il metodo NotifyParent in un provider di concetti dinamici è un callback eseguito dal modello di dati principale quando viene eseguita una manipolazione statica del modello padre singolo dell'oggetto. Per qualsiasi modello padre specificato aggiunto, questo metodo verrà chiamato una prima volta quando viene aggiunto il modello padre e una seconda volta se/quando viene rimosso il modello padre.
NotifyDestruct di IDynamicConceptProviderConcept
Il metodo NotifyDestruct su un provider di concetti dinamici è un callback eseguito dal modello di dati di base all'inizio della distruzione dell'oggetto che è un provider di concetti dinamici. Offre ulteriori opportunità di pulizia per i clienti che lo richiedono.
--
Vedere anche
Questo argomento fa parte di una serie che descrive le interfacce accessibili da C++, come usarle per compilare 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
Oggetti C++ del modello di dati del debugger
Interfacce aggiuntive del modello di dati del debugger C++