Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier les répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer de répertoire.
Cette rubrique décrit les concepts du modèle de données C++ du débogueur.
Concepts dans le modèle de données
Les objets synthétiques dans le modèle de données sont effectivement deux éléments :
- Dictionnaire de tuples clé/valeur/métadonnées.
- Ensemble de concepts (interfaces) pris en charge par le modèle de données. Les concepts sont des interfaces qu’un client (par opposition au modèle de données) implémente pour fournir un ensemble spécifié de comportement sémantique. L’ensemble de concepts actuellement pris en charge est répertorié ici.
| Interface de Concept | Descriptif |
|---|---|
| IDataModelConcept | Le concept est un modèle parent. Si ce modèle est automatiquement attaché à un type natif via une signature de type inscrite, la méthode InitializeObject est appelée automatiquement chaque fois qu’un nouvel objet de ce type est instancié. |
| IStringDisplayableConcept | L’objet peut être converti en chaîne à des fins d’affichage. |
| IIterableConcept | L’objet est un conteneur et peut être itéré. |
| IIndexableConcept | L’objet est un conteneur et peut être indexé (accessible via un accès aléatoire) dans une ou plusieurs dimensions. |
| IPreferredRuntimeTypeConcept | L’objet comprend plus sur les types dérivés de celui-ci que le système de type sous-jacent est capable de fournir et souhaite gérer ses propres conversions de type statique en type d’exécution. |
| IDynamicKeyProviderConcept | L’objet est un fournisseur dynamique de clés et souhaite prendre en charge toutes les requêtes clés à partir du modèle de données de base. Cette interface est généralement utilisée comme pont vers des langages dynamiques tels que JavaScript. |
| IDynamicConceptProviderConcept | L’objet est un fournisseur dynamique de concepts et souhaite prendre en charge toutes les requêtes de concept à partir du modèle de données de base. Cette interface est généralement utilisée comme pont vers des langages dynamiques tels que JavaScript. |
Concept de modèle de données : IDataModelConcept
Tout objet de modèle attaché à un autre objet de modèle en tant que modèle parent doit prendre directement en charge le concept de modèle de données. Le concept de modèle de données nécessite la prise en charge d’une interface, IDataModelConcept défini comme suit.
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 modèle de données peut être inscrit en tant que visualiseur canonique ou en tant qu’extension pour un type natif donné via les méthodes RegisterModelForTypeSignature ou RegisterExtensionForTypeSignature du gestionnaire de modèles de données. Lorsqu’un modèle est inscrit via l’une de ces méthodes, le modèle de données est automatiquement attaché en tant que modèle parent à n’importe quel objet natif dont le type correspond à la signature passée dans l’inscription. Au moment où cette pièce jointe est automatiquement effectuée, la méthode InitializeObject est appelée sur le modèle de données. Il est passé l’objet d’instance, la signature de type qui a provoqué la pièce jointe et un énumérateur qui produit les instances de type (dans l’ordre linéaire) qui correspondent à tous les caractères génériques dans la signature de type. L’implémentation du modèle de données peut utiliser cet appel de méthode pour initialiser les caches dont elle a besoin.
Si un modèle de données donné est inscrit sous un nom par défaut via la méthode RegisterNamedModel, l’interface IDataModelConcept du modèle de données inscrit doit retourner ce nom à partir de cette méthode. Notez qu’il est parfaitement légitime qu’un modèle soit inscrit sous plusieurs noms (la valeur par défaut ou la meilleure doit être retournée ici). Un modèle peut être complètement sans nom (tant qu’il n’est pas inscrit sous un nom). Dans de telles circonstances, la méthode GetName doit retourner E_NOTIMPL.
Le Concept Displayable de String : IStringDisplayableConcept
Un objet qui souhaite fournir une conversion de chaîne à des fins d’affichage peut implémenter le concept d’affichage de chaîne via l’implémentation de l’interface IStringDisplayableConcept. L’interface est définie comme suit :
DECLARE_INTERFACE_(IStringDisplayableConcept, IUnknown)
{
STDMETHOD(ToDisplayString)(_In_ IModelObject* contextObject, _In_opt_ IKeyStore* metadata, _Out_ BSTR* displayString) PURE;
}
La méthode ToDisplayString est appelée chaque fois qu’un client souhaite convertir un objet en chaîne à afficher (dans la console, dans l’interface utilisateur, etc.). Une telle conversion de chaîne ne doit pas être utilisée pour la base d’une manipulation programmatique supplémentaire. La conversion de chaîne elle-même peut être profondément influencée par les métadonnées passées à l’appel. Une conversion de chaîne doit effectuer chaque tentative d’honorer les clés PreferredRadix et PreferredFormat.
Le concept itérable : IIterableConcept et IModelIterator
Un objet qui est un conteneur d’autres objets et souhaite exprimer la possibilité d’itérer sur ces objets contenus peut prendre en charge le concept itérable par une implémentation des interfaces IIterableConcept et IModelIterator. Il existe une relation très importante entre la prise en charge du concept itérable et la prise en charge du concept indexable. Un objet qui prend en charge l’accès aléatoire aux objets contenus peut prendre en charge le concept indexable en plus du concept itérable. Dans ce cas, les éléments itérés doivent également produire un index par défaut qui, lorsqu’ils sont passés au concept indexable font référence au même objet. Un échec de satisfaction de cet invariant entraîne un comportement non défini dans l’hôte de débogage.
IIterableConcept est défini comme suit :
DECLARE_INTERFACE_(IIterableConcept, IUnknown)
{
STDMETHOD(GetDefaultIndexDimensionality)(_In_ IModelObject* contextObject, _Out_ ULONG64* dimensionality) PURE;
STDMETHOD(GetIterator)(_In_ IModelObject* contextObject, _Out_ IModelIterator** iterator) PURE;
}
Le concept IModelIterator est défini comme suit :
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 d’IIterableConcept
La méthode GetDefaultIndexDimensionality retourne le nombre de dimensions à l’index par défaut. Si un objet n’est pas indexable, cette méthode doit retourner 0 et réussir (S_OK). Tout objet qui retourne une valeur non nulle de cette méthode déclare la prise en charge d’un contrat de protocole qui indique :
- L'objet prend en charge le concept indexable grâce à la prise en charge d'IIndexableConcept.
- La méthode GetNext de l’IModelIterator retournée par la méthode GetIterator du concept itérable retourne un index par défaut unique pour chaque élément produit. Ce type d’index aura le nombre de dimensions indiquées ici.
- Le passage des index retournés par la méthode GetNext de l’IModelIterator à la méthode GetAt sur le concept indexable (IIndexableConcept) fait référence au même objet que GetNext produit. La même valeur est retournée.
Itérabilité de IIterableConcept : GetIterator
La méthode GetIterator sur le concept itérable retourne une interface d’itérateur qui peut être utilisée pour itérer l’objet. L’itérateur retourné doit mémoriser l’objet de contexte passé à la méthode GetIterator. Elle ne sera pas transmise aux méthodes sur l’itérateur lui-même.
Réinitialisation de IModelIterator
La méthode Reset sur un itérateur retourné à partir du concept itérable restaure la position de l’itérateur sur l’emplacement où il était lors de la création de l’itérateur (avant le premier élément). Bien qu’il soit fortement recommandé que l’itérateur prend en charge la méthode Reset, il n’est pas nécessaire. Un itérateur peut être l’équivalent d’un itérateur d’entrée C++ et autoriser uniquement une seule transmission d’itération vers l’avant. Dans ce cas, la méthode Reset peut échouer avec E_NOTIMPL.
GetNext d’IModelIterator
La méthode GetNext déplace l’itérateur vers l’avant et récupère l’élément itéré suivant. Si l’objet est indexable en plus d’être itérable et qu’il est indiqué par l’argument GetDefaultIndexDimensionality retournant une valeur non nulle, cette méthode peut éventuellement renvoyer les index par défaut pour revenir à la valeur produite à partir de l’indexeur. Notez qu’un appelant peut choisir de passer 0/nullptr et de ne pas récupérer d’index. Il est considéré comme illégal pour l’appelant de demander des indices partiels (par exemple, inférieur au nombre produit par GetDefaultIndexDimensionality).
Si l’itérateur a été déplacé vers l’avant, mais qu’une erreur s’est produite lors de la lecture de la valeur de l’élément itéré, la méthode peut renvoyer une erreur ET remplir « object » avec un objet d’erreur. À la fin de l’itération des éléments contenus, l’itérateur retourne E_BOUNDS à partir de la méthode GetNext. Tout appel ultérieur (sauf s’il y a eu un appel de réinitialisation intermédiaire) retourne également E_BOUNDS.
Le concept indexable : IIndexableConcept
Un objet qui souhaite fournir un accès aléatoire à un ensemble de contenu peut prendre en charge le concept indexable via la prise en charge de l’interface IIndexableConcept. Les objets qui sont indexables sont généralement itérables, car ils prennent en charge le concept d'itérabilité. Cela n’est toutefois pas obligatoire. Si elle est prise en charge, il existe une relation importante entre l’itérateur et l’indexeur. L’itérateur doit prendre en charge GetDefaultIndexDimensionality, retourner une valeur non nulle par cette méthode, et prendre en charge le contrat tel que documenté là-bas. L’interface de concept de l’indexeur est définie comme suit :
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;
}
Un exemple d’utilisation de l’indexeur (et de son interaction avec l’itérateur) est illustré ci-dessous. Cet exemple itère le contenu d’un conteneur indexable et utilise l’indexeur pour revenir à la valeur qui vient d’être retournée. Bien que cette opération soit fonctionnellement inutile comme écrit, elle montre comment ces interfaces interagissent. Notez que l’exemple ci-dessous ne traite pas de l’échec d’allocation de mémoire. Il part du principe qu'il y a un lancer d'exception (ce qui peut constituer un mauvais postulat en fonction de l'environnement dans lequel le code se trouve - les méthodes COM du modèle de données ne peuvent pas avoir des exceptions C++ échappées) :
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.
//
}
}
}
}
La méthode GetDimensionality retourne le nombre de dimensions dans laquelle l’objet est indexé. Notez que si l’objet est à la fois itérable et indexable, l’implémentation de GetDefaultIndexDimensionality doit être d’accord avec l’implémentation de GetDimensionality quant au nombre de dimensions dont dispose l’indexeur.
La méthode GetAt récupère la valeur à un index ndimensionnel particulier à partir de l’objet indexé. Indexeur de dimensions N où N est la valeur retournée par GetDimensionality doit être prise en charge. Notez qu’un objet peut être indexable dans différents domaines par différents types (par exemple, indexable via des ordinals et des chaînes). Si l’index est hors plage (ou n’a pas pu être accessible), la méthode retourne un échec ; Toutefois, dans ce cas, l’objet de sortie peut toujours être défini sur un objet d’erreur.
La méthode SetAt tente de définir la valeur à un index ndimensionnel particulier à partir de l’objet indexé. Indexeur de dimensions N où N est la valeur retournée par GetDimensionality doit être prise en charge. Notez qu’un objet peut être indexable dans différents domaines par différents types (par exemple, indexable via des ordinals et des chaînes). Certains indexeurs sont en lecture seule. Dans ce cas, E_NOTIMPL est retournée à partir d’un appel à la méthode SetAt.
Concept de type d’exécution préféré : IPreferredRuntimeTypeConcept
Un hôte de débogage peut être interrogé pour tenter de déterminer le type d’exécution réel d’un objet à partir d’un type statique trouvé dans des informations symboliques. Cette conversion peut être basée sur des informations complètement précises (par exemple, C++ RTTI) ou basée sur des heuristiques fortes telles que la forme de toutes les tables de fonctions virtuelles au sein de l’objet. Toutefois, certains objets ne peuvent pas être convertis d’un type statique en type d’exécution, car ils ne tiennent pas dans les heuristiques de l’hôte de débogage (par exemple, ils n’ont pas de table de fonction virtuelle ou RTTI). Dans ce cas, un modèle de données pour un objet peut choisir de remplacer le comportement par défaut et déclarer qu’il en sait plus sur le « type d’exécution » d’un objet que l’hôte de débogage est capable de comprendre. Cela s’effectue via le concept de type d’exécution préféré et la prise en charge de l’interface IPreferredRuntimeTypeConcept.
L’interface IPreferredRuntimeTypeConcept est déclarée comme suit :
DECLARE_INTERFACE_(IPreferredRuntimeTypeConcept, IUnknown)
{
STDMETHOD(CastToPreferredRuntimeType)(_In_ IModelObject* contextObject, _COM_Errorptr_ IModelObject** object) PURE;
}
La méthode CastToPreferredRuntimeType est appelée chaque fois qu’un client souhaite tenter de convertir d’une instance de type statique en type d’exécution de cette instance. Si l’objet en question prend en charge (via l’un de ses modèles parents attachés) le concept de type d’exécution préféré, cette méthode est appelée pour effectuer la conversion. Cette méthode peut renvoyer l’objet d’origine (il n’y a pas de conversion ou il n’a pas pu être analysé), retourner une nouvelle instance du type d’exécution, échouer pour des raisons non sémantiques (par exemple : absence de mémoire) ou retourner E_NOT_SET. Le code d’erreur E_NOT_SET est un code d’erreur très spécial qui indique au modèle de données que l’implémentation ne souhaite pas remplacer le comportement par défaut et que le modèle de données doit revenir à l’analyse effectuée par l’hôte de débogage (par exemple : analyse RTTI, examen de la forme des tables de fonctions virtuelles, etc...)
Concepts du fournisseur dynamique : IDynamicKeyProviderConcept et IDynamicConceptProviderConcept
Bien que le modèle de données lui-même gère normalement la gestion des clés et des concepts pour les objets, il existe des moments où cette notion est inférieure à l’idéal. En particulier, lorsqu’un client souhaite créer un pont entre le modèle de données et quelque chose d’autre qui est vraiment dynamique (par exemple, JavaScript), il peut être utile de prendre en charge la gestion des clés et des concepts à partir de l’implémentation dans le modèle de données. Étant donné que le modèle de données de base est l’une et la seule implémentation d’IModelObject, cela est effectué par le biais d’une combinaison de deux concepts : le concept de fournisseur de clés dynamiques et le concept de fournisseur de concept dynamique. Bien qu’il soit courant de mettre en œuvre les deux ou ni l’un ni l’autre, il n’est pas nécessaire de le faire.
Si les deux sont implémentés, le concept de fournisseur de clés dynamiques doit être ajouté avant le concept de fournisseur de concept dynamique. Ces deux concepts sont spéciaux. Ils retournent efficacement un commutateur sur l’objet qui passe de « statiquement géré » à « géré dynamiquement ». Ces concepts ne peuvent être définis que s’il n’existe pas de clés/concepts gérés par le modèle de données sur l’objet. Une fois ces concepts ajoutés à un objet, l’action de procéder est irréversible.
Il existe une différence sémantique supplémentaire autour de l’extensibilité entre un IModelObject qui est un fournisseur de concept dynamique et un autre qui n’est pas. Ces concepts sont destinés à permettre aux clients de créer des ponts entre le modèle de données et les systèmes de langage dynamique tels que JavaScript. Le modèle de données a un concept d’extensibilité qui diffère quelque peu fondamentalement des systèmes comme JavaScript dans le fait qu’il existe une arborescence de modèles parents plutôt qu’une chaîne linéaire comme la chaîne de prototype JavaScript. Pour permettre une meilleure relation avec ces systèmes, un IModelObject, qui est un fournisseur de concept dynamique a un seul parent de modèle de données. Ce parent de modèle de données unique est un IModelObject normal qui peut avoir un nombre arbitraire de modèles parents, comme c’est le cas pour le modèle de données. Toutes les demandes adressées au fournisseur de concept dynamique pour ajouter ou supprimer des parents sont automatiquement redirigées vers le parent unique. Du point de vue d’un extérieur, il semble que le fournisseur de concept dynamique a une chaîne de style d’arborescence normale de modèles parents. L’implémenteur du concept de fournisseur de concept dynamique est le seul objet (en dehors du modèle de données de base) qui est conscient du parent unique intermédiaire. Ce parent unique peut être lié au système de langage dynamique pour fournir un pont (par exemple, placé dans la chaîne de prototype JavaScript).
Le concept de fournisseur de clés dynamiques est défini comme suit :
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;
}
Le concept de fournisseur de concept dynamique est défini comme suit :
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;
}
GetKey d’IDynamicKeyProviderConcept
La méthode GetKey sur un fournisseur de clés dynamiques est en grande partie un remplacement de la méthode GetKey sur IModelObject. Le fournisseur de clés dynamiques est censé retourner la valeur de la clé et toutes les métadonnées associées à cette clé. Dans le cas où la clé n’est pas présente (mais aucune autre erreur ne se produit), le fournisseur doit retourner false dans le paramètre hasKey et réussir avec S_OK. L’échec de cet appel est considéré comme un échec de récupération d’une clé et arrête explicitement la recherche de la clé via la chaîne de modèle parent. Le retour de la valeur false dans hasKey et la réussite continuent la recherche de la clé. Notez qu’il est parfaitement légal pour GetKey de renvoyer un accesseur de propriété boxed en tant que clé. Cela serait sémantiquement identique à la méthode GetKey sur IModelObject retournant un accesseur de propriété.
SetKey d’IDynamicKeyProviderConcept
La méthode SetKey sur un fournisseur de clés dynamiques est effectivement un remplacement de la méthode SetKey sur IModelObject. Cela définit une clé dans le fournisseur dynamique. Il s’agit effectivement de la création d’une nouvelle propriété sur le fournisseur. Notez qu’un fournisseur qui ne prend pas en charge une notion de quelque chose comme la création de propriétés expando doit retourner E_NOTIMPL ici.
IDynamicKeyProviderConcept : EnumerateKeys
La méthode EnumerateKeys sur un fournisseur de clés dynamiques est effectivement un remplacement de la méthode EnumerateKeys sur IModelObject. Cela énumère toutes les clés du fournisseur dynamique. L’énumérateur retourné a plusieurs restrictions qui doivent être respectées par l’implémentation :
- Il doit se comporter comme un appel à EnumerateKeys et non à EnumerateKeyValues ou à EnumerateKeyReferences. Elle doit retourner les valeurs de clé qui ne résout aucun accesseur de propriété sous-jacent (si ce concept existe dans le fournisseur).
- Du point de vue d’un seul fournisseur de clés dynamiques, il est illégal d’énumérer plusieurs clés du même nom que les clés physiquement distinctes. Cela peut se produire sur différents fournisseurs attachés par le biais de la chaîne de modèle parent, mais il ne peut pas se produire du point de vue d’un seul fournisseur.
GetConcept De IDynamicConceptProviderConcept
La méthode GetConcept sur un fournisseur de concept dynamique est effectivement un remplacement de la méthode GetConcept sur IModelObject. Le fournisseur de concept dynamique doit retourner une interface pour le concept interrogé s’il existe ainsi que les métadonnées associées à ce concept. Si le concept n’existe pas sur le fournisseur, il doit être indiqué via une valeur false retournée dans l’argument hasConcept et un retour réussi. L’échec de cette méthode est un échec de récupération du concept et arrête explicitement la recherche du concept. Le retour de false pour hasConcept et un code réussi continuera la recherche du concept par le biais de l’arborescence du modèle parent.
Le SetConcept de IDynamicConceptProviderConcept
La méthode SetConcept sur un fournisseur de concept dynamique est effectivement un remplacement de la méthode SetConcept sur IModelObject. Le fournisseur dynamique attribue le concept. Cela peut rendre l’objet itérable, indexable, convertible en chaîne, etc. Notez qu’un fournisseur qui n’autorise pas la création de concepts sur celui-ci doit retourner E_NOPTIMPL ici.
NotifyParent de IDynamicConceptProviderConcept
L’appel NotifyParent sur un fournisseur de concept dynamique est utilisé par le modèle de données de base pour informer le fournisseur dynamique du modèle parent unique qui est créé pour permettre de combler le paradigme « plusieurs modèles parents » du modèle de données vers des langages plus dynamiques. Toute manipulation de ce modèle parent unique entraîne d’autres notifications au fournisseur dynamique. Notez que ce rappel est effectué immédiatement lors de l’affectation du concept de fournisseur de concept dynamique.
NotifyParentChange de IDynamicConceptProviderConcept
La méthode NotifyParent sur un fournisseur de concept dynamique est un rappel effectué par le modèle de données de base lorsqu’une manipulation statique du modèle parent unique de l’objet est effectuée. Pour tout modèle parent donné ajouté, cette méthode est appelée une première fois lorsque le modèle parent est ajouté et une deuxième fois si/quand le modèle parent est supprimé.
NotifyDestruct de IDynamicConceptProviderConcept
La méthode NotifyDestruct sur un fournisseur de concept dynamique est un rappel effectué par le modèle de données de base au début de la destruction de l’objet, qui est un fournisseur de concept dynamique. Il offre des opportunités de nettoyage supplémentaires aux clients qui en ont besoin.
--
Voir aussi
Cette rubrique fait partie d’une série qui décrit les interfaces accessibles à partir de C++, comment les utiliser pour générer une extension de débogueur C++ et comment utiliser d’autres constructions de modèle de données (par exemple, JavaScript ou NatVis) à partir d’une extension de modèle de données C++.
Vue d’ensemble du modèle de données du débogueur C++
Interfaces du modèle de données C++ du débogueur
Objets C++ du modèle de données du débogueur
Modèle de Données du Débogueur Interfaces C++ supplémentaires