Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Thema werden Konzepte im Debugger-C++-Datenmodell beschrieben.
Konzepte im Datenmodell
Synthetische Objekte im Datenmodell sind effektiv zwei Dinge:
- Ein Wörterbuch mit Schlüssel-/Wert-/Metadaten-Tupeln.
- Eine Reihe von Konzepten (Schnittstellen), die vom Datenmodell unterstützt werden. Konzepte sind Schnittstellen, die ein Client (im Gegensatz zum Datenmodell) implementiert, um einen bestimmten Satz semantischer Verhaltensweisen bereitzustellen. Die derzeit unterstützten Konzepte sind hier aufgeführt.
Konzeptschnittstelle | BESCHREIBUNG |
---|---|
IDataModelConcept | Das Konzept ist ein übergeordnetes Modell. Wenn dieses Modell automatisch über eine registrierte Typsignatur an einen systemeigenen Typ angefügt wird, wird die InitializeObject-Methode automatisch aufgerufen, wenn ein neues Objekt dieses Typs instanziiert wird. |
IStringDarstellbaresKonzept | Das Objekt kann zu Anzeigezwecken in eine Zeichenfolge konvertiert werden. |
IIterableConcept | Das Objekt ist ein Container und kann durchlaufen werden. |
IIndexableConcept | Das Objekt ist ein Container und kann in einem oder mehreren Dimensionen indiziert werden (über zufälligen Zugriff darauf zugegriffen werden). |
IPreferredRuntimeTypeConcept | Das Objekt versteht mehr über typen, die daraus abgeleitet werden, als das zugrunde liegende Typsystem in der Lage ist, eigene Konvertierungen von statisch in Laufzeittyp zu behandeln. |
DynamischerSchlüsselanbieterKonzept | Das Objekt ist ein dynamischer Schlüsselanbieter und möchte alle Schlüsselabfragen aus dem Kerndatenmodell übernehmen. Diese Schnittstelle wird in der Regel als Brücke zu dynamischen Sprachen wie JavaScript verwendet. |
IDynamicConceptProviderConcept | Das Objekt ist ein dynamischer Anbieter von Konzepten und möchte alle Konzeptabfragen aus dem Kerndatenmodell übernehmen. Diese Schnittstelle wird in der Regel als Brücke zu dynamischen Sprachen wie JavaScript verwendet. |
Das Datenmodellkonzept: IDataModelConcept
Jedes Modellobjekt, das einem anderen Modellobjekt als übergeordnetes Modell zugeordnet ist, muss das Datenmodellkonzept direkt unterstützen. Das Datenmodellkonzept erfordert unterstützung einer Schnittstelle, IDataModelConcept definiert wie folgt.
DECLARE_INTERFACE_(IDataModelConcept, IUnknown)
{
STDMETHOD(InitializeObject)(_In_ IModelObject* modelObject, _In_opt_ IDebugHostTypeSignature* matchingTypeSignature, _In_opt_ IDebugHostSymbolEnumerator* wildcardMatches) PURE;
STDMETHOD(GetName)(_Out_ BSTR* modelName) PURE;
}
Ein Datenmodell kann als kanonischer Visualizer oder als Erweiterung für einen bestimmten systemeigenen Typ über die Methoden RegisterModelForTypeSignature oder RegisterExtensionForTypeSignature registriert werden. Wenn ein Modell über eine dieser Methoden registriert wird, wird das Datenmodell automatisch als übergeordnetes Modell an jedes systemeigene Objekt angefügt, dessen Typ mit der in der Registrierung übergebenen Signatur übereinstimmt. An der Stelle, an der diese Anlage automatisch erstellt wird, wird die InitializeObject-Methode für das Datenmodell aufgerufen. Es wird das Instanzobjekt, die Typsignatur übergeben, die die Anlage verursacht hat, und einen Enumerator, der die Typinstanzen (in linearer Reihenfolge) erzeugt, die allen Wildcards in der Typsignatur entsprechen. Die Datenmodellimplementierung kann diesen Methodenaufruf verwenden, um alle benötigten Caches zu initialisieren.
Wenn ein angegebenes Datenmodell unter einem Standardnamen über die RegisterNamedModel-Methode registriert ist, muss die IDataModelConcept-Schnittstelle des registrierten Datenmodells diesen Namen von dieser Methode zurückgeben. Beachten Sie, dass es vollkommen legitim ist, dass ein Modell unter mehreren Namen registriert wird (der Standardwert oder die beste sollte hier zurückgegeben werden). Ein Modell kann vollständig unbenannt sein (solange es nicht unter einem Namen registriert ist). Unter solchen Umständen sollte die GetName-Methode E_NOTIMPL zurückgeben.
Das Konzept der anzeigbaren Zeichenfolge: IStringDisplayableConcept
Ein Objekt, das eine Zeichenfolgenkonvertierung für Anzeigezwecke bereitstellen möchte, kann das Zeichenfolgenanzeigekonzept durch Implementierung der IStringDisplayableConcept-Schnittstelle implementieren. Die Schnittstelle ist wie folgt definiert:
DECLARE_INTERFACE_(IStringDisplayableConcept, IUnknown)
{
STDMETHOD(ToDisplayString)(_In_ IModelObject* contextObject, _In_opt_ IKeyStore* metadata, _Out_ BSTR* displayString) PURE;
}
Die ToDisplayString-Methode wird immer aufgerufen, wenn ein Client ein Objekt in eine anzuzeigende Zeichenfolge (in konsole, in der Benutzeroberfläche usw.) konvertieren möchte. Eine solche Zeichenfolgenkonvertierung sollte nicht für die Grundlage zusätzlicher programmgesteuerter Manipulationen verwendet werden. Die Zeichenfolgenkonvertierung selbst kann durch die an den Aufruf übergebenen Metadaten tief beeinflusst werden. Bei einer Zeichenfolgenkonvertierung sollte jeder Versuch unternommen werden, die Schlüssel "PreferredRadix" und "PreferredFormat" zu berücksichtigen.
Das iterable Konzept: IIterableConcept und IModelIterator
Ein Objekt, das ein Container anderer Objekte ist und die Fähigkeit zum Durchlaufen dieser enthaltenen Objekte ausdrücken möchte, kann das iterierbare Konzept durch eine Implementierung der IIterableConcept- und IModelIterator-Schnittstellen unterstützen. Es gibt eine sehr wichtige Beziehung zwischen Der Unterstützung des iterierbaren Konzepts und der Unterstützung des indizierbaren Konzepts. Ein Objekt, das den zufälligen Zugriff auf die enthaltenen Objekte unterstützt, kann das indizierbare Konzept zusätzlich zum iterierbaren Konzept unterstützen. In diesem Fall müssen die iterierten Elemente auch einen Standardindex erzeugen, der beim Übergeben an das indizierbare Konzept auf dasselbe Objekt verweist. Ein Fehler bei der Erfüllung dieser Invariante führt zum nicht definierten Verhalten im Debughost.
Das IIterableConcept ist wie folgt definiert:
DECLARE_INTERFACE_(IIterableConcept, IUnknown)
{
STDMETHOD(GetDefaultIndexDimensionality)(_In_ IModelObject* contextObject, _Out_ ULONG64* dimensionality) PURE;
STDMETHOD(GetIterator)(_In_ IModelObject* contextObject, _Out_ IModelIterator** iterator) PURE;
}
Das IModelIterator-Konzept ist wie folgt definiert:
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;
}
IIterableConcept's GetDefaultIndexDimensionality
Die GetDefaultIndexDimensionality-Methode gibt die Anzahl der Dimensionen an den Standardindex zurück. Wenn ein Objekt nicht indiziert werden kann, sollte diese Methode 0 zurückgeben und erfolgreich (S_OK). Jedes Objekt, das einen Wert ungleich Null aus dieser Methode zurückgibt, deklariert die Unterstützung für einen Protokollvertrag, der folgendes angibt:
- Das Objekt unterstützt das indizierbare Konzept durch Unterstützung von IIndexableConcept.
- Die GetNext-Methode des von der GetIterator-Methode des iterierbaren Konzepts zurückgegebenen IModelIterator gibt einen eindeutigen Standardindex für jedes produzierte Element zurück. Dieser Index hat die Anzahl der Dimensionen, wie hier angegeben.
- Wenn die von der GetNext-Methode des IModelIterator zurückgegebenen Indizes an die GetAt-Methode für das indizierbare Konzept (IIndexableConcept) übergeben werden, wird auf dasselbe Objekt verwiesen, das Von GetNext erzeugt wurde. Derselbe Wert wird zurückgegeben.
IIterableConcepts GetIterator
Die GetIterator-Methode für das iterierbare Konzept gibt eine Iteratorschnittstelle zurück, die zum Durchlaufen des Objekts verwendet werden kann. Der zurückgegebene Iterator muss sich an das Kontextobjekt erinnern, das an die GetIterator-Methode übergeben wurde. Sie wird nicht an Methoden für den Iterator selbst übergeben.
IModelIterator Zurücksetzen
Die Reset-Methode für einen Iterator, der vom iterierbaren Konzept zurückgegeben wird, stellt die Position des Iterators wieder her, an der es war, als der Iterator zum ersten Mal erstellt wurde (vor dem ersten Element). Es wird zwar dringend empfohlen, die Reset-Methode von Iterator zu unterstützen, es ist jedoch nicht erforderlich. Ein Iterator kann das Äquivalent eines C++-Eingabe-Iterators sein und nur einen einzelnen Durchlauf der Vorwärtsiteration zulassen. In diesem Fall kann die Reset-Methode mit E_NOTIMPL fehlschlagen.
IModelIterator's GetNext
Die GetNext-Methode verschiebt den Iterator vorwärts und ruft das nächste iterierte Element ab. Wenn das Objekt zusätzlich zu iterierbar ist und dies durch das Argument GetDefaultIndexDimensionality angegeben wird, das einen Wert ungleich Null zurückgibt, kann diese Methode optional die Standardindizes zurückgeben, um zum erzeugten Wert vom Indexer zurückzukehren. Beachten Sie, dass ein Aufrufer wählen kann, 0/nullptr zu übergeben und keine Indizes abzurufen. Es gilt als illegal, dass der Aufrufer Teilindizes anfordert (z. B.: kleiner als die von GetDefaultIndexDimensionality erzeugte Zahl).
Wenn der Iterator erfolgreich vorwärts verschoben wurde, aber beim Lesen des Werts des iterierten Elements ein Fehler aufgetreten ist, kann die Methode einen Fehler zurückgeben UND das "Objekt" mit einem Fehlerobjekt füllen. Am Ende der Iteration der enthaltenen Elemente gibt der Iterator E_BOUNDS aus der GetNext-Methode zurück. Alle nachfolgenden Aufrufe (es sei denn, es wurde ein Rückruf dazwischen gestellt) wird auch E_BOUNDS zurückgegeben.
Das indizierbare Konzept: IIndexableConcept
Ein Objekt, das zufälligen Zugriff auf eine Gruppe von Inhalten ermöglichen möchte, kann das indizierbare Konzept über die Unterstützung der IIndexableConcept-Schnittstelle unterstützen. Die meisten Objekte, die indiziert werden können, werden auch durch Unterstützung des iterierbaren Konzepts iterierbar sein. Dies ist jedoch nicht erforderlich. Wenn dies unterstützt wird, gibt es eine wichtige Beziehung zwischen iterator und Indexer. Der Iterator muss die GetDefaultIndexDimensionality unterstützen, einen Wert ungleich Null aus dieser Methode zurückgeben und den dort dokumentierten Vertrag unterstützen. Die Indexer-Konzeptschnittstelle ist wie folgt definiert:
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;
}
Nachfolgend sehen Sie ein Beispiel für die Verwendung des Indexers (und dessen Zusammenspiel mit dem Iterator). In diesem Beispiel wird der Inhalt eines indizierbaren Containers durchlaufen und der Indexer verwendet, um zum soeben zurückgegebenen Wert zurückzukehren. Während dieser Vorgang funktionell nutzlos wie geschrieben ist, wird gezeigt, wie diese Schnittstellen interagieren. Beachten Sie, dass im folgenden Beispiel kein Speicherzuweisungsfehler auftritt. Es wird angenommen, dass eine neue throw-Ausdruck verwendet wird (was eine schlechte Annahme sein könnte, je nach der Umgebung, in der sich der Code befindet – die COM-Methoden des Datenmodells können keine C++-Ausnahmen entkommen lassen).
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.
//
}
}
}
}
Die GetDimensionality-Methode gibt die Anzahl der Dimensionen zurück, in denen das Objekt indiziert ist. Beachten Sie, dass die Implementierung von GetDefaultIndexDimensionality, wenn das Objekt sowohl iterierbar als auch indiziert werden kann, mit der Implementierung von GetDimensionality einverstanden sein muss, wie viele Dimensionen der Indexer hat.
Die GetAt-Methode ruft den Wert bei einem bestimmten N-dimensionalen Index aus dem indizierten Objekt ab. Ein Indexer von N-Dimensionen, wobei N der von "GetDimensionality" zurückgegebene Wert ist, muss unterstützt werden. Beachten Sie, dass ein Objekt in verschiedenen Domänen durch verschiedene Typen indiziert werden kann (z. B. über Ordinale und Zeichenfolgen indiziert). Wenn sich der Index außerhalb des Bereichs befindet (oder nicht darauf zugegriffen werden konnte), gibt die Methode einen Fehler zurück. In solchen Fällen kann das Ausgabeobjekt jedoch weiterhin auf ein Fehlerobjekt festgelegt werden.
Die SetAt-Methode versucht, den Wert auf einen bestimmten N-dimensionalen Index innerhalb des indizierten Objekts festzulegen. Ein Indexer von N-Dimensionen, wobei N der von "GetDimensionality" zurückgegebene Wert ist, muss unterstützt werden. Beachten Sie, dass ein Objekt in verschiedenen Domänen durch verschiedene Typen indiziert werden kann (z. B. über Ordinale und Zeichenfolgen indiziert). Einige Indexer sind schreibgeschützt. In solchen Fällen wird E_NOTIMPL von jedem Aufruf der SetAt-Methode zurückgegeben.
Das bevorzugte Laufzeittypkonzept: IPreferredRuntimeTypeConcept
Ein Debughost kann abgefragt werden, um zu versuchen, den realen Laufzeittyp eines Objekts aus einem statischen Typ zu ermitteln, der in symbolischen Informationen enthalten ist. Diese Konvertierung kann auf vollständig genauen Informationen (z. B. C++ RTTI) basieren oder auf starken Heuristiken wie der Form aller virtuellen Funktionstabellen innerhalb des Objekts basieren. Einige Objekte können jedoch nicht von einer statischen in einen Laufzeittyp konvertiert werden, da sie nicht in die Heuristik des Debughosts passen (z. B.: sie haben keine RTTI- oder virtuellen Funktionstabellen). In solchen Fällen kann ein Datenmodell für ein Objekt das Standardverhalten außer Kraft setzen und deklarieren, dass es mehr über den "Laufzeittyp" eines Objekts weiß, als der Debughost verständnisfähig ist. Dies erfolgt über das bevorzugte Laufzeittypkonzept und die Unterstützung der IPreferredRuntimeTypeConcept-Schnittstelle.
Die IPreferredRuntimeTypeConcept-Schnittstelle wird wie folgt deklariert:
DECLARE_INTERFACE_(IPreferredRuntimeTypeConcept, IUnknown)
{
STDMETHOD(CastToPreferredRuntimeType)(_In_ IModelObject* contextObject, _COM_Errorptr_ IModelObject** object) PURE;
}
Die CastToPreferredRuntimeType-Methode wird immer aufgerufen, wenn ein Client versuchen möchte, von einer statischen Typinstanz in den Laufzeittyp dieser Instanz zu konvertieren. Wenn das betreffende Objekt (über eines seiner angefügten übergeordneten Modelle) das bevorzugte Laufzeittypkonzept unterstützt, wird diese Methode aufgerufen, um die Konvertierung auszuführen. Diese Methode kann entweder das ursprüngliche Objekt zurückgeben (es gibt keine Konvertierung oder konnte nicht analysiert werden), eine neue Instanz des Laufzeittyps zurückgeben, aus nicht semantischen Gründen fehlschlagen (z. B. nicht genügend Arbeitsspeicher) oder E_NOT_SET zurückgeben. Der E_NOT_SET Fehlercode ist ein sehr spezieller Fehlercode, der für das Datenmodell angibt, dass die Implementierung das Standardverhalten nicht außer Kraft setzen möchte und dass das Datenmodell auf die vom Debughost durchgeführte Analyse zurückgreifen sollte (z. B. RTTI-Analyse, Untersuchung der Form der virtuellen Funktionstabellen, usw.
Die Konzepte des dynamischen Anbieters: IDynamicKeyProviderConcept und IDynamicConceptProviderConcept
Während das Datenmodell selbst normalerweise die Schlüssel- und Konzeptverwaltung für Objekte verarbeitet, gibt es Zeiten, in denen dieser Begriff weniger als ideal ist. Insbesondere, wenn ein Kunde eine Brücke zwischen dem Datenmodell und etwas anderes erstellen möchte, das wirklich dynamisch ist (z. B. JavaScript), kann es hilfreich sein, die Schlüssel- und Konzeptverwaltung von der Implementierung im Datenmodell zu übernehmen. Da das Kerndatenmodell die einzige Implementierung von IModelObject ist, erfolgt dies stattdessen über eine Kombination aus zwei Konzepten: dem dynamischen Schlüsselanbieterkonzept und dem dynamischen Konzeptanbieterkonzept. Obwohl es typisch wäre, beide oder keines zu implementieren, besteht keine Anforderung dafür.
Wenn beide implementiert werden, muss das dynamische Schlüsselanbieterkonzept vor dem Konzept des dynamischen Konzeptanbieters hinzugefügt werden. Beide Konzepte sind besonders. Sie kippen effektiv einen Schalter auf dem Objekt, der ihn von "statisch verwaltet" in "dynamisch verwaltet" ändert. Diese Konzepte können nur festgelegt werden, wenn es keine Schlüssel/Konzepte gibt, die vom Datenmodell für das Objekt verwaltet werden. Sobald diese Konzepte zu einem Objekt hinzugefügt werden, ist die Aktion dieser Aktion unwiderruflich.
Es gibt einen zusätzlichen semantischen Unterschied bei der Erweiterbarkeit zwischen einem IModelObject, bei dem es sich um einen dynamischen Konzeptanbieter handelt und nicht. Diese Konzepte sollen Es Clients ermöglichen, Brücken zwischen dem Datenmodell und dynamischen Sprachsystemen wie JavaScript zu erstellen. Das Datenmodell hat ein Konzept der Erweiterbarkeit, das sich grundlegend von Systemen wie JavaScript unterscheidet, da es eine Struktur von übergeordneten Modellen anstelle einer linearen Kette wie der JavaScript-Prototypkette gibt. Um eine bessere Beziehung zu solchen Systemen zu ermöglichen, verfügt ein IModelObject, das ein dynamischer Konzeptanbieter ist, über ein einzelnes Übergeordnetes Datenmodell. Dieses einzelne übergeordnete Datenmodell ist ein normales IModelObject, das eine beliebige Anzahl von übergeordneten Modellen aufweisen kann, wie es für Datenmodelle typisch ist. Alle Anforderungen an den dynamischen Konzeptanbieter zum Hinzufügen oder Entfernen von Eltern werden automatisch an das einzelne Elternteil umgeleitet. Aus Außensicht sieht es so aus, als ob der dynamische Konzeptanbieter über eine normale Strukturstilkette von übergeordneten Modellen verfügt. Der Implementierer des Konzepts des dynamischen Konzeptanbieters ist das einzige Objekt (außerhalb des Kerndatenmodells), das sich der übergeordneten Zwischenstufe bewusst ist. Dieses einzelne übergeordnete Element kann mit dem dynamischen Sprachsystem verknüpft werden, um eine Brücke bereitzustellen (z. B. in die JavaScript-Prototypkette platziert).
Das Konzept des dynamischen Schlüsselanbieters wird wie folgt definiert:
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;
}
Das Konzept des dynamischen Konzeptanbieters ist wie folgt definiert:
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;
}
IDynamicKeyProviderConcepts GetKey
Die GetKey-Methode für einen dynamischen Schlüsselanbieter ist weitgehend eine Außerkraftsetzung der GetKey-Methode für IModelObject. Der dynamische Schlüsselanbieter wird erwartet, dass der Wert des Schlüssels und alle Metadaten zurückgegeben werden, die diesem Schlüssel zugeordnet sind. Wenn der Schlüssel nicht vorhanden ist (aber kein anderer Fehler auftritt), muss der Anbieter "false" im hasKey-Parameter zurückgeben und mit S_OK erfolgreich sein. Wenn dieser Aufruf fehlschlägt, wird ein Fehler beim Abrufen eines Schlüssels betrachtet und die Suche nach dem Schlüssel über die übergeordnete Modellkette explizit angehalten. Wenn "false" in hasKey zurückgegeben wird, wird die Suche nach dem Schlüssel fortgesetzt. Beachten Sie, dass es für GetKey vollkommen legal ist, einen Box-Eigenschaftsaccessor als Schlüssel zurückzugeben. Dies wäre semantisch identisch mit der GetKey-Methode für IModelObject, die einen Eigenschaftsaccessor zurückgibt.
Das SetKey von IDynamicKeyProviderConcept
Die SetKey-Methode für einen dynamischen Schlüsselanbieter ist effektiv eine Außerkraftsetzung der SetKey-Methode für IModelObject. Dadurch wird ein Schlüssel im dynamischen Anbieter festgelegt. Es ist effektiv die Schaffung einer neuen Eigenschaft auf dem Anbieter. Beachten Sie, dass ein Anbieter, der keine Vorstellung von etwas wie der Erstellung von expando-Eigenschaften unterstützt, hier E_NOTIMPL zurückgeben sollte.
IDynamicKeyProviderConcept's EnumerateKeys
Die EnumerateKeys-Methode für einen dynamischen Schlüsselanbieter ist effektiv eine Außerkraftsetzung der EnumerateKeys-Methode auf IModelObject. Dadurch werden alle Schlüssel im dynamischen Anbieter aufgelistet. Der zurückgegebene Enumerator hat mehrere Einschränkungen, die von der Implementierung berücksichtigt werden müssen:
- Sie muss sich als Aufruf von EnumerateKeys und nicht als EnumerateKeyValues oder EnumerateKeyReferences verhalten. Sie muss die Schlüsselwerte zurückgeben, die keine zugrunde liegenden Eigenschaftsaccessoren auflösen (sofern ein solches Konzept im Anbieter vorhanden ist).
- Aus Sicht eines einzelnen dynamischen Schlüsselanbieters ist es unzulässig, mehrere Schlüssel mit demselben Namen aufzählen zu können, die physisch voneinander getrennt sind. Dies kann bei verschiedenen Anbietern geschehen, die über die übergeordnete Modellkette angefügt sind, aber nicht aus sicht eines einzelnen Anbieters geschehen.
IDynamicConceptProviderConcept's GetConcept
Die GetConcept-Methode für einen dynamischen Konzeptanbieter ist effektiv eine Außerkraftsetzung der GetConcept-Methode auf IModelObject. Der dynamische Konzeptanbieter muss eine Schnittstelle für das abgefragte Konzept zurückgeben, sofern es vorhanden ist, sowie alle Metadaten, die diesem Konzept zugeordnet sind. Wenn das Konzept für den Anbieter nicht vorhanden ist, muss dies über einen falsch zurückgegebenen Wert im hasConcept-Argument und einer erfolgreichen Rückgabe angegeben werden. Fehler dieser Methode ist ein Fehler beim Abrufen des Konzepts und wird die Suche nach dem Konzept explizit anhalten. Gibt "false" für hasConcept zurück, und ein erfolgreicher Code setzt die Suche nach dem Konzept über die übergeordnete Modellstruktur fort.
IDynamicConceptProviderConcepts SetConcept
Die SetConcept-Methode für einen dynamischen Konzeptanbieter ist effektiv eine Außerkraftsetzung der SetConcept-Methode auf IModelObject. Der dynamische Anbieter weist das Konzept zu. Dies kann dazu führen, dass das Objekt iterierbar, indiziert, Zeichenfolge konvertierbar usw. wird... Beachten Sie, dass ein Anbieter, der die Erstellung von Konzepten nicht zulässt, hier E_NOPTIMPL zurückgeben sollte.
IDynamicConceptProviderConcept's NotifyParent
Der NotifyParent-Aufruf eines dynamischen Konzeptanbieters wird vom Kerndatenmodell verwendet, um den dynamischen Anbieter des einzelnen übergeordneten Modells zu informieren, das erstellt wird, um das Paradigma "mehrere übergeordnete Modelle" des Datenmodells mit dynamischeren Sprachen zu überbrücken. Jede Manipulation dieses einzelnen übergeordneten Modells führt zu weiteren Benachrichtigungen an den dynamischen Anbieter. Beachten Sie, dass dieser Rückruf unmittelbar nach Zuweisung des Konzepts des dynamischen Konzeptanbieters erfolgt.
Die Methode NotifyParentChange des IDynamicConceptProviderConcept
Die NotifyParent-Methode für einen dynamischen Konzeptanbieter ist ein Rückruf des Kerndatenmodells, wenn eine statische Manipulation des einzelnen übergeordneten Modells des Objekts vorgenommen wird. Für jedes hinzugefügte übergeordnete Modell wird diese Methode zum ersten Mal aufgerufen, wenn das übergeordnete Modell hinzugefügt wird, und ein zweites Mal, wenn/wann das übergeordnete Modell entfernt wird.
NotifyDestruct von IDynamicConceptProviderConcept
Die NotifyDestruct-Methode eines dynamischen Konzeptanbieters ist ein Rückruf des Kerndatenmodells zu Beginn der Zerstörung des Objekts, das ein dynamischer Konzeptanbieter ist. Es bietet zusätzliche Bereinigungsmöglichkeiten für Kunden, die sie erfordern.
--
Siehe auch
Dieses Thema ist Teil einer Reihe, in der die von C++ zugänglichen Schnittstellen beschrieben werden, wie sie zum Erstellen einer C++-basierten Debuggererweiterung und zur Verwendung anderer Datenmodellkonstrukte (z. B. JavaScript oder NatVis) aus einer C++-Datenmodellerweiterung verwendet werden.
Übersicht über das Debuggerdatenmodell C++
Debuggerdatenmodell-C++-Schnittstellen
Debugger-Datenmodell-C++-Objekte