Share via


Concepts C++ du modèle de données du débogueur

Cette rubrique décrit les concepts du modèle de données C++ débogueur.

Concepts dans le modèle de données

Les objets synthétiques dans le modèle de données sont en fait deux choses :

  • 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 comportements sémantiques. L’ensemble de concepts actuellement pris en charge est répertorié ici.
Concept Interface Description
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 automatiquement appelée 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 mieux les types dérivés que le système de type sous-jacent est capable de fournir et souhaite gérer ses propres conversions du type statique au type runtime.
IDynamicKeyProviderConcept L’objet est un fournisseur dynamique de clés et souhaite prendre en charge toutes les requêtes clés 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 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 qui est 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éfinie 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;
}

InitializeObject

Un modèle de données peut être inscrit en tant que visualiseur canonique ou en tant qu’extension pour un type natif donné par le biais des 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 à tout 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 reçoit l’objet instance, la signature de type à l’origine de la pièce jointe et un énumérateur qui produit les instances de type (dans l’ordre linéaire) qui correspondent aux caractères génériques de 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.

GetName

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 ce cas, la méthode GetName doit retourner E_NOTIMPL.

Concept d’affichage de chaîne : IStringDisplayableConcept

Un objet qui souhaite fournir une conversion de chaîne à des fins d’affichage peut implémenter le concept de chaîne affichable par le biais de l’implémentation de l’interface IStringDisplayableConcept. L’interface se définit comme suit :

DECLARE_INTERFACE_(IStringDisplayableConcept, IUnknown)
{
    STDMETHOD(ToDisplayString)(_In_ IModelObject* contextObject, _In_opt_ IKeyStore* metadata, _Out_ BSTR* displayString) PURE;
}

ToDisplayString

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 pour respecter les clés PreferredRadix et PreferredFormat.

Le concept itérable : IIterableConcept et IModelIterator

Un objet qui est un conteneur d’autres objets et qui 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’il est passé au concept indexable, fait référence au même objet. Si vous ne répondez pas à cet invariant, vous obtiendrez 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 autre que zéro à partir 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 via la prise en charge de 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. Un tel index aura le nombre de dimensions indiqué ici.
  • La transmission des indics retournées à partir de la méthode GetNext de l’IModelIterator à la méthode GetAt sur le concept indexable (IIndexableConcept) fait référence à l’objet produit par GetNext. La même valeur est retournée.

GetIterator d’IIterableConcept

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 qui a été passé à la méthode GetIterator. Il ne sera pas transmis aux méthodes sur l’itérateur lui-même.

Réinitialisation d’IModelIterator

La méthode Reset sur un itérateur retourné à partir du concept itérable restaure la position de l’itérateur à l’emplacement où il se trouvait lors de la création initiale 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, elle n’est pas obligatoire. Un itérateur peut être l’équivalent d’un itérateur d’entrée C++ et n’autoriser qu’une seule passe 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 extrait l’élément itéré suivant. Si l’objet est indexable en plus d’être itérable et que cela est indiqué par l’argument GetDefaultIndexDimensionality retournant une valeur autre que zéro, cette méthode peut éventuellement retourner les indicies 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’indics. 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 avancé avec succès, mais qu’une erreur s’est produite lors de la lecture de la valeur de l’élément itéré, la méthode peut retourner 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 de la méthode GetNext. Tout appel suivant (sauf s’il y a eu un appel de réinitialisation intermédiaire) retourne également E_BOUNDS.

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. La plupart des objets indexables seront également itérables grâce à la prise en charge du concept itérable. Toutefois, cela n’est pas obligatoire. S’il est pris 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 différente de zéro à partir de cette méthode et prendre en charge le contrat documenté ici. 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 telle qu’elle est écrite, elle montre comment ces interfaces interagissent. Notez que l’exemple ci-dessous ne traite pas les échecs d’allocation de mémoire. Il suppose qu’une nouvelle levée (ce qui peut être une mauvaise hypothèse en fonction de l’environnement dans lequel le code existe ; les méthodes COM du modèle de données ne peuvent pas avoir d’exceptions C++ d’échappement) :

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 indicies.
            //
            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.
                //
            }
        }
    }
}

GetDimensionality

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 correspondre à l’implémentation de GetDimensionality quant au nombre de dimensions dont dispose l’indexeur.

GetAt

La méthode GetAt récupère la valeur à un index N dimensionnel particulier à partir de l’objet indexé. Un indexeur de N-dimensions où N est la valeur retournée par GetDimensionality doit être pris 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 limites (ou n’est pas 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.

SetAt

La méthode SetAt tente de définir la valeur à un index N dimensionnel particulier à partir de l’objet indexé. Un indexeur de N-dimensions où N est la valeur retournée par GetDimensionality doit être pris 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é à partir de n’importe quel 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 les informations symboliques. Cette conversion peut être basée sur des informations totalement exactes (par exemple, RTTI C++) ou 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 un type runtime, car ils ne tiennent pas dans l’heuristique de l’hôte de débogage (par exemple, ils n’ont pas de RTTI ou de tables de fonctions virtuelles). 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 n’est en mesure de comprendre. Pour ce faire, vous utilisez 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;
}

CastToPreferredRuntimeType

La méthode CastToPreferredRuntimeType est appelée chaque fois qu’un client souhaite tenter de passer d’un type statique instance au type d’exécution de ce 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 un nouveau instance du type d’exécution, échouer pour des raisons non sémantiques (par exemple: mémoire insuffisante) 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 n’est pas idéale. En particulier, lorsqu’un client souhaite créer un pont entre le modèle de données et quelque chose d’autre réellement 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 la seule et unique implémentation d’IModelObject, cette opération est effectuée via 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 d’implémenter les deux ou ni l’un ni l’autre, il n’est pas nécessaire de les mettre en œuvre.

Si les deux sont implémentés, le concept de fournisseur de clé dynamique doit être ajouté avant le concept de fournisseur de concept dynamique. Ces deux concepts sont spéciaux. Ils basculent efficacement un commutateur sur l’objet en le remplaçant de « géré statiquement » à « géré dynamiquement ». Ces concepts ne peuvent être définis que s’il n’y a 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 cette action est irrévocable.

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 ne l’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 en ce qu’il existe une arborescence de modèles parents plutôt qu’une chaîne linéaire comme la chaîne 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 généralement 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 étranger, il semble que le fournisseur de concept dynamique ait 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 connaît le 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 de 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é dynamique est censé retourner la valeur de la clé et toutes les métadonnées associées à cette clé. Si la clé n’est pas présente (mais qu’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 d’extraction d’une clé et interrompt explicitement la recherche de la clé via la chaîne de modèle parent. Le retour de false dans hasKey et success poursuit la recherche de la clé. Notez qu’il est parfaitement légal pour GetKey de retourner un accesseur de propriété boxed comme clé. Cela serait sémantiquement identique à la méthode GetKey sur IModelObject retournant un accesseur de propriété.

SetKey de IDynamicKeyProviderConcept

La méthode SetKey sur un fournisseur de clés dynamiques est en fait un remplacement de la méthode SetKey sur IModelObject. Cette opération définit une clé dans le fournisseur dynamique. Il s’agit en fait de la création d’une nouvelle propriété sur le fournisseur. Notez qu’un fournisseur qui ne prend en charge aucune notion de quelque chose comme la création de propriétés expando doit retourner E_NOTIMPL ici.

EnumerateKeys de IDynamicKeyProviderConcept

La méthode EnumerateKeys sur un fournisseur de clé dynamique est en fait un remplacement de la méthode EnumerateKeys sur IModelObject. Cette opération é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. Il doit retourner les valeurs de clé sans résoudre les accesseurs de propriété sous-jacents (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 qui sont des clés physiquement distinctes. Cela peut se produire sur différents fournisseurs attachés via la chaîne de modèle parent, mais cela 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 en fait 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 toutes les métadonnées associées à ce concept. Si le concept n’existe pas sur le fournisseur, cela 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 interrompt explicitement la recherche du concept. Le retour de false pour hasConcept et un code réussi poursuit la recherche du concept via l’arborescence du modèle parent.

SetConcept d’IDynamicConceptProviderConcept

La méthode SetConcept sur un fournisseur de concept dynamique est en fait 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 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 le pontage du paradigme des « modèles parents multiples » 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 après l’attribution du concept de fournisseur de concept dynamique.

NotifyParentChange de IDynamicConceptProviderProvider

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 un modèle parent donné ajouté, cette méthode est appelée une première fois lors de l’ajout du modèle parent 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 propre 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 créer 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 C++ du débogueur

Interfaces C++ du modèle de données du débogueur

Objets C++ du modèle de données du débogueur

Interfaces supplémentaires C++ du modèle de données du débogueur

Concepts C++ du modèle de données du débogueur

Script C++ du modèle de données du débogueur