Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In dit onderwerp worden concepten in het C++-gegevensmodel van het foutopsporingsprogramma beschreven.
Concepten in het gegevensmodel
Synthetische objecten in het gegevensmodel zijn in feite twee dingen:
- Een woordenlijst met sleutel/waarde/metagegevens-tupels.
- Een set concepten (interfaces) die worden ondersteund door het gegevensmodel. Concepten zijn interfaces die een client (in plaats van het gegevensmodel) implementeert om een opgegeven set semantisch gedrag te bieden. De momenteel ondersteunde set concepten wordt hier vermeld.
| Conceptinterface | Beschrijving |
|---|---|
| IDataModelConcept | Het concept is een moedermodel. Als dit model automatisch wordt gekoppeld aan een systeemeigen type via een handtekening van een geregistreerd type, wordt de methode InitializeObject automatisch aangeroepen wanneer een nieuw object van dit type wordt geïnstantieerd. |
| IStringDisplayableConcept | Het object kan worden geconverteerd naar een tekenreeks voor weergavedoeleinden. |
| IIterableConcept | Het object is een container en kan worden geïtereerd. |
| IIndexableConcept | Het object is een container en kan worden geïndexeerd (toegankelijk via willekeurige toegang) in een of meer dimensies. |
| IPreferredRuntimeTypeConcept | Het object begrijpt meer over typen die ermee zijn afgeleid dan het onderliggende typesysteem kan bieden en wil zijn eigen conversies verwerken van statisch naar runtime-type. |
| IDynamicKeyProviderConcept | Het object is een dynamische provider van sleutels en wil alle sleutelquery's van het kerngegevensmodel overnemen. Deze interface wordt doorgaans gebruikt als een brug naar dynamische talen, zoals JavaScript. |
| IDynamicConceptProviderConceptConcept | Het object is een dynamische provider van concepten en wil alle conceptquery's van het kerngegevensmodel overnemen. Deze interface wordt doorgaans gebruikt als een brug naar dynamische talen, zoals JavaScript. |
Het gegevensmodelconcept: IDataModelConcept
Elk modelobject dat is gekoppeld aan een ander modelobject als een bovenliggende modelobject, moet het concept van het gegevensmodel rechtstreeks ondersteunen. Het gegevensmodelconcept vereist ondersteuning van een interface, IDataModelConcept die als volgt is gedefinieerd.
DECLARE_INTERFACE_(IDataModelConcept, IUnknown)
{
STDMETHOD(InitializeObject)(_In_ IModelObject* modelObject, _In_opt_ IDebugHostTypeSignature* matchingTypeSignature, _In_opt_ IDebugHostSymbolEnumerator* wildcardMatches) PURE;
STDMETHOD(GetName)(_Out_ BSTR* modelName) PURE;
}
Een gegevensmodel kan worden geregistreerd als canonieke visualizer of als een extensie voor een bepaald systeemeigen type via de methoden RegisterModelForTypeSignature of RegisterExtensionForTypeSignature van de gegevensmodelbeheerder. Wanneer een model wordt geregistreerd via een van deze methoden, wordt het gegevensmodel automatisch als bovenliggend model gekoppeld aan elk systeemeigen object waarvan het type overeenkomt met de handtekening die in de registratie is doorgegeven. Op het punt waar die bijlage automatisch wordt gemaakt, wordt de methode InitializeObject aangeroepen op het gegevensmodel. Het wordt doorgegeven aan het exemplaarobject, de typehandtekening die de bijlage heeft veroorzaakt en een enumerator die de typeexemplaren produceert (in lineaire volgorde) die overeenkomen met jokertekens in de typehandtekening. De implementatie van het gegevensmodel kan deze methode-aanroep gebruiken om caches te initialiseren die nodig zijn.
Als een bepaald gegevensmodel is geregistreerd onder een standaardnaam via de methode RegisterNamedModel, moet de IDataModelConcept-interface van het geregistreerde gegevensmodel die naam retourneren uit deze methode. Houd er rekening mee dat het perfect legitiem is dat een model wordt geregistreerd onder meerdere namen (de standaard of beste moet hier worden geretourneerd). Een model kan volledig naamloos zijn (zolang het niet is geregistreerd onder een naam). In dergelijke omstandigheden moet de Methode GetName E_NOTIMPL retourneren.
Het tekenreeksweergaveconcept: IStringDisplayableConcept
Een object dat een tekenreeksconversie voor weergavedoeleinden wil bieden, kan het weergaveconcept voor tekenreeksen implementeren via de implementatie van de IStringDisplayableConcept-interface. De interface wordt als volgt gedefinieerd:
DECLARE_INTERFACE_(IStringDisplayableConcept, IUnknown)
{
STDMETHOD(ToDisplayString)(_In_ IModelObject* contextObject, _In_opt_ IKeyStore* metadata, _Out_ BSTR* displayString) PURE;
}
De methode ToDisplayString wordt aangeroepen wanneer een client een object wil converteren naar een tekenreeks die moet worden weergegeven (naar console, in de gebruikersinterface, enzovoort). Een dergelijke tekenreeksconversie mag niet worden gebruikt voor de basis van aanvullende programmatische manipulatie. De tekenreeksconversie zelf kan sterk worden beïnvloed door de metagegevens die bij de aanroep worden meegegeven. Bij een tekenreeksconversie moet elke poging worden uitgevoerd om de sleutels PreferredRadix en PreferredFormat te respecteren.
Het iterable concept: IIterableConcept en IModelIterator
Een object dat een container van andere objecten is en de mogelijkheid wil uitdrukken om deze ingesloten objecten te herhalen, kan het iterable concept ondersteunen door een implementatie van de IIterableConcept- en IModelIterator-interfaces. Er is een zeer belangrijke relatie tussen de ondersteuning van het iterable concept en de ondersteuning van het indexeerbare concept. Een object dat willekeurige toegang tot de ingesloten objecten ondersteunt, kan het indexeerbare concept naast het iterable concept ondersteunen. In dit geval moeten de itereerde elementen ook een standaardindex produceren die, wanneer doorgegeven aan het indexeerbare concept, naar hetzelfde object verwijst. Een fout om aan deze invariant te voldoen, resulteert in niet-gedefinieerd gedrag in de host voor foutopsporing.
De IIterableConcept wordt als volgt gedefinieerd:
DECLARE_INTERFACE_(IIterableConcept, IUnknown)
{
STDMETHOD(GetDefaultIndexDimensionality)(_In_ IModelObject* contextObject, _Out_ ULONG64* dimensionality) PURE;
STDMETHOD(GetIterator)(_In_ IModelObject* contextObject, _Out_ IModelIterator** iterator) PURE;
}
Het IModelIterator Concept wordt als volgt gedefinieerd:
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 van IIterableConcept
De methode GetDefaultIndexDimensionality retourneert het aantal dimensies naar de standaardindex. Als een object niet kan worden geïndexeerbaar, moet deze methode 0 retourneren en voltooien (S_OK). Elk object dat een niet-nulwaarde van deze methode retourneert, geeft ondersteuning aan voor een protocolcontract met de volgende status:
- Het object ondersteunt het indexeerbare concept via ondersteuning van IIndexableConcept
- De GetNext-methode van de IModelIterator die is geretourneerd door de GetIterator-methode van het iterable concept retourneert een unieke standaardindex voor elk geproduceerd element. Een dergelijke index heeft het aantal dimensies zoals hier wordt aangegeven.
- Het doorgeven van de indexen die zijn geretourneerd door de GetNext-methode van de IModelIterator aan de GetAt-methode voor het indexeerbare concept (IIndexableConcept) verwijst naar hetzelfde object dat GetNext heeft geproduceerd. Dezelfde waarde wordt geretourneerd.
IIterableConcept's GetIterator
De Methode GetIterator op het iterable concept retourneert een iterator-interface die kan worden gebruikt om het object te herhalen. De geretourneerde iterator moet het contextobject onthouden dat is doorgegeven aan de GetIterator-methode. Het wordt niet doorgegeven aan methoden op de iterator zelf.
IModelIterator's opnieuw instellen
Met de methode Reset op een iterator die wordt geretourneerd op basis van het iterable concept, wordt de positie van de iterator hersteld naar de locatie waar de iterator voor het eerst werd gemaakt (vóór het eerste element). Hoewel het sterk wordt aanbevolen dat iterator de methode Reset ondersteunt, is dit niet vereist. Een iterator kan het equivalent zijn van een C++-invoer-iterator en mag slechts één doorgang van voorwaartse iteratie toestaan. In zo'n geval kan de Reset-methode mislukken met E_NOTIMPL.
GetNext van IModelIterator
De GetNext-methode verplaatst de iterator naar voren en haalt het volgende iterrated-element op. Als het object, naast dat het doorlopen kan worden, ook kan worden geïndexeerd en dit wordt aangegeven door het argument GetDefaultIndexDimensionality dat een niet-nulwaarde retourneert, kan deze methode optioneel de standaardindexen retourneren om via de indexeerder terug te keren naar de geproduceerde waarde. Een beller kan ervoor kiezen om 0/nullptr door te geven en geen indexen op te halen. Het wordt als illegaal beschouwd voor de beller om gedeeltelijke indexen aan te vragen (bijvoorbeeld: kleiner dan het aantal dat is geproduceerd door GetDefaultIndexDimensionality).
Als de iterator met succes vooruit is gegaan maar er een fout is opgetreden bij het lezen van de waarde van het geïtereerde element, kan de methode een foutmelding retourneren EN 'object' vullen met een foutobject. Aan het einde van de iteratie van de ingesloten elementen retourneert de iterator E_BOUNDS van de GetNext-methode. Elke volgende aanroep (tenzij er een tussenliggende reset-aanroep is) retourneert ook E_BOUNDS.
Het indexeerbare concept: IIndexableConcept
Een object dat willekeurige toegang tot een set inhoud wil bieden, kan het indexeerbare concept ondersteunen via de IIndexableConcept-interface. De meeste objecten die geïndexeerd kunnen worden, kunnen ook worden doorlopen door ondersteuning van het iterable-concept. Dit is echter niet vereist. Indien ondersteund, is er een belangrijke relatie tussen de iterator en de indexeerfunctie. De iterator moet de GetDefaultIndexDimensionality ondersteunen, een niet-nulwaarde van die methode retourneren en het daar gedocumenteerde contract ondersteunen. De conceptinterface van de indexeerfunctie wordt als volgt gedefinieerd:
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;
}
Hieronder ziet u een voorbeeld van het gebruik van de indexeerfunctie (en de bijbehorende interactie met de iterator). In dit voorbeeld wordt de inhoud van een indexeerbare container herhaald en wordt de indexeerfunctie gebruikt om terug te gaan naar de waarde die zojuist is geretourneerd. Hoewel deze bewerking functioneel nutteloos is zoals geschreven, laat het zien hoe deze interfaces communiceren. Houd er rekening mee dat het onderstaande voorbeeld niet te maken heeft met een fout in de geheugentoewijzing. Er wordt uitgegaan van een 'throwing new' (wat, afhankelijk van de omgeving waarin de code zich bevindt, een slechte aanname kan zijn: de COM-methoden van het gegevensmodel kunnen geen C++-uitzonderingen buiten laten komen):
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.
//
}
}
}
}
De methode GetDimensionality retourneert het aantal dimensies waarin het object is geïndexeerd. Als het object zowel itereerbaar als indexeerbaar is, moet de implementatie van GetDefaultIndexDimensionality overeenkomen met de implementatie van GetDimensionality met betrekking tot het aantal dimensies dat de indexeerfunctie heeft.
De Methode GetAt haalt de waarde op een bepaalde N-dimensionale index op vanuit het geïndexeerde object. Een indexeerfunctie van N-dimensies waarbij N de waarde is die wordt geretourneerd door GetDimensionality, moet worden ondersteund. Houd er rekening mee dat een object kan worden geïndexeerd in verschillende domeinen door verschillende typen (bijvoorbeeld: indexeerbaar via zowel ordinals als tekenreeksen). Als de index buiten het bereik valt (of niet kan worden geopend), retourneert de methode een fout; In dergelijke gevallen kan het uitvoerobject echter nog steeds worden ingesteld op een foutobject.
De Methode SetAt probeert de waarde in te stellen op een bepaalde N-dimensionale index vanuit het geïndexeerde object. Een indexeerfunctie van N-dimensies waarbij N de waarde is die wordt geretourneerd door GetDimensionality, moet worden ondersteund. Houd er rekening mee dat een object kan worden geïndexeerd in verschillende domeinen door verschillende typen (bijvoorbeeld: indexeerbaar via zowel ordinals als tekenreeksen). Sommige indexeerfuncties zijn alleen-lezen. In dergelijke gevallen wordt E_NOTIMPL geretourneerd bij elke oproep naar de methode SetAt.
Het concept van het type voorkeursruntime: IPreferredRuntimeTypeConcept
Een debug-host kan worden opgevraagd om te trachten het werkelijke runtimetype van een object te bepalen van een statisch type dat in de symbolische informatie wordt gevonden. Deze conversie kan zijn gebaseerd op volledig nauwkeurige informatie (bijvoorbeeld C++ RTTI) of is gebaseerd op sterke heuristieken, zoals de vorm van virtuele functietabellen in het object. Sommige objecten kunnen echter niet worden geconverteerd van een statisch naar een runtimetype omdat ze niet in de heuristiek van de foutopsporingshost passen (bijvoorbeeld: ze hebben geen RTTI- of virtuele functietabellen). In dergelijke gevallen kan een gegevensmodel voor een object ervoor kiezen om het standaardgedrag te overschrijven en te declareren dat het meer weet over het 'runtimetype' van een object dan dat de foutopsporingshost kan begrijpen. Dit wordt gedaan via het concept van het voorkeursruntimetype en de ondersteuning van de interface IPreferredRuntimeTypeConcept.
De interface IPreferredRuntimeTypeConcept wordt als volgt gedeclareerd:
DECLARE_INTERFACE_(IPreferredRuntimeTypeConcept, IUnknown)
{
STDMETHOD(CastToPreferredRuntimeType)(_In_ IModelObject* contextObject, _COM_Errorptr_ IModelObject** object) PURE;
}
De methode CastToPreferredRuntimeType wordt aangeroepen wanneer een client probeert te converteren van een statisch type exemplaar naar het runtimetype van dat exemplaar. Als het betreffende object (via een van de gekoppelde bovenliggende modellen) het voorkeursconcept van het runtimetype ondersteunt, wordt deze methode aangeroepen om de conversie uit te voeren. Deze methode kan het oorspronkelijke object retourneren (er is geen conversie of het kan niet worden geanalyseerd), een nieuw exemplaar van het runtimetype retourneren, mislukken om niet-semantische redenen (bijvoorbeeld onvoldoende geheugen) of retourneren E_NOT_SET. De E_NOT_SET foutcode is een zeer speciale foutcode die aangeeft aan het gegevensmodel dat de implementatie niet het standaardgedrag wil overschrijven en dat het gegevensmodel moet terugvallen op de analyse die wordt uitgevoerd door de foutopsporingshost (bijvoorbeeld: RTTI-analyse, onderzoek van de vorm van de virtuele functietabellen, etc...)
De concepten van dynamische providers: IDynamicKeyProviderConcept en IDynamicConceptProviderConcept
Hoewel het gegevensmodel zelf normaal gesproken sleutel- en conceptbeheer voor objecten afhandelt, zijn er situaties waarin dat begrip minder is dan ideaal. Met name wanneer een klant een brug wil maken tussen het gegevensmodel en iets anders dat echt dynamisch is (bijvoorbeeld JavaScript), kan het waardevol zijn om sleutel- en conceptbeheer over te nemen van de implementatie in het gegevensmodel. Omdat het kerngegevensmodel de enige en enige implementatie van IModelObject is, wordt dit gedaan via een combinatie van twee concepten: het concept van de dynamische sleutelprovider en het concept van de dynamische conceptprovider. Hoewel het gebruikelijk zou zijn om beide of geen van beide te implementeren, is hiervoor geen vereiste.
Als beide worden geïmplementeerd, moet het concept van de dynamische sleutelprovider worden toegevoegd vóór het concept van de dynamische conceptprovider. Beide concepten zijn speciaal. Ze zetten effectief een schakelaar om op het object, waardoor het wordt gewijzigd van 'statisch beheerd' naar 'dynamisch beheerd'. Deze concepten kunnen alleen worden ingesteld als er geen sleutels/concepten zijn die worden beheerd door het gegevensmodel op het object. Zodra deze concepten aan een object zijn toegevoegd, is de actie om dit te doen onherroepelijk.
Er is een extra semantisch verschil rond uitbreidbaarheid tussen een IModelObject, een dynamische conceptprovider en een die niet is. Deze concepten zijn bedoeld om clients in staat te stellen bruggen te maken tussen het gegevensmodel en dynamische taalsystemen zoals JavaScript. Het gegevensmodel heeft een concept van uitbreidbaarheid dat enigszins fundamenteel verschilt van systemen zoals JavaScript, omdat er een structuur van bovenliggende modellen is in plaats van een lineaire keten zoals de JavaScript-prototypeketen. Een IModelObject dat een dynamische conceptprovider is, heeft één bovenliggend gegevensmodel om een betere relatie met dergelijke systemen mogelijk te maken. Het enkele bovenliggende gegevensmodel is een normaal IModelObject dat een willekeurig aantal bovenliggende modellen kan hebben, zoals gebruikelijk is voor het gegevensmodel. Aanvragen bij de dynamische conceptprovider om ouders toe te voegen of te verwijderen, worden automatisch omgeleid naar het enkele bovenliggende element. Vanuit het perspectief van een buitenstaander lijkt het alsof de dynamische conceptprovider een normale boomstructuur van bovenliggende modellen heeft. De implementeerfunctie van het concept van de dynamische conceptprovider is het enige object (buiten het kerngegevensmodel) dat op de hoogte is van het tussenliggende bovenliggende element. Die ene ouder kan worden gekoppeld aan het dynamische taalsysteem om een verbinding te bieden (bijvoorbeeld in de JavaScript-prototypeketen).
Het concept van de dynamische sleutelprovider wordt als volgt gedefinieerd:
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;
}
Het concept van de dynamische conceptprovider wordt als volgt gedefinieerd:
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 van IDynamicKeyProviderConcept
De GetKey-methode op een dynamische sleutelprovider is grotendeels een override van de GetKey-methode op IModelObject. De provider van dynamische sleutels retourneert naar verwachting de waarde van de sleutel en alle metagegevens die aan die sleutel zijn gekoppeld. Als de sleutel niet aanwezig is (maar er geen andere fout optreedt), moet de provider false retourneren in de hasKey-parameter en met succes S_OK retourneren. Als deze oproep mislukt, wordt dit beschouwd als een fout bij het ophalen van een sleutel en zal de zoekopdracht naar de sleutel door de bovenliggende modelketen expliciet worden stopgezet. Als false wordt geretourneerd in hasKey en success, dan wordt de zoekopdracht naar de sleutel voortgezet. Houd er rekening mee dat het volledig legaal is voor GetKey om een geboxte eigenschapstoegangsmethode als sleutel te retourneren. Dit zou semantisch identiek zijn aan de GetKey-methode op IModelObject die een eigenschapstoegangsobject retourneert.
SetKey van IDynamicKeyProviderConcept
De methode SetKey op een dynamische sleutelprovider is in feite een overschrijving van de methode SetKey op IModelObject. Hiermee stelt u een sleutel in bij de dynamische provider. Het is in feite het creëren van een nieuwe eigenschap bij de provider. Houd er rekening mee dat een provider die geen ondersteuning biedt voor iets als het maken van expando-eigenschappen, hier E_NOTIMPL moet retourneren.
EnumerateKeys van IDynamicKeyProviderConcept
De methode EnumerateKeys van een dynamische-sleutelprovider is in feite een overschrijving van de methode EnumerateKeys van IModelObject. Hiermee worden alle sleutels in de dynamische provider opgesomd. De geretourneerde enumerator heeft verschillende beperkingen die moeten worden gerespecteerd door de implementatie.
- Het moet zich gedragen als een oproep van EnumerateKeys en niet van EnumerateKeyValues of EnumerateKeyReferences. Het moet de sleutelwaarden retourneren zonder enige onderliggende eigenschapsaccessors op te lossen (als zulk concept in de provider bestaat).
- Vanuit het perspectief van één dynamische sleutelprovider is het illegaal om meerdere sleutels met dezelfde naam op te sommen die fysiek afzonderlijke sleutels zijn. Dit kan gebeuren op verschillende providers die zijn gekoppeld via de bovenliggende modelketen, maar dit kan niet gebeuren vanuit het perspectief van één provider.
GetConcept van IDynamicConceptProviderConcept
De methode GetConcept op een dynamische conceptprovider is feitelijk een overschrijving van de methode GetConcept op IModelObject. De dynamische conceptprovider moet een interface retourneren voor het queryconcept als deze bestaat, evenals metagegevens die aan dat concept zijn gekoppeld. Als het concept niet bestaat bij de provider, moet dit worden aangegeven door een foutieve waarde die wordt geretourneerd in het argument hasConcept en een succesvolle terugkeer. Het mislukken van deze methode is een fout bij het ophalen van het concept en stopt expliciet de zoekopdracht naar het concept. Het retourneren van onwaar voor hasConcept en een geslaagde code zal de zoektocht naar het concept voortzetten via de bovenliggende modelboom.
IDynamicConceptProviderConcept's SetConcept van IDynamicConcept
De methode SetConcept op een dynamische conceptprovider is in feite een overschrijving van de methode SetConcept op IModelObject. De dynamische provider wijst het concept toe. Hierdoor kan het object doorzoekbaar, indexeerbaar, converteren naar een tekenreeks, enz. worden. Houd er rekening mee dat een provider die het maken van concepten niet toestaat, hier E_NOPTIMPL moet teruggeven.
IDynamicConceptProviderConcept's NotifyParent
De NotifyParent-aanroep van een dynamische conceptprovider wordt door het centrale gegevensmodel gebruikt om de dynamische provider van het een enkele bovenliggende model te informeren, dat is gecreëerd om het 'meerdere bovenliggende modellen'-paradigma van het gegevensmodel te overbruggen naar dynamische programmeertalen. Elke manipulatie van dat ene bovenliggende model veroorzaakt verdere meldingen aan de dynamische provider. Houd er rekening mee dat deze callback direct wordt uitgevoerd bij het toewijzen van het concept van de dynamische conceptprovider.
De NotifyParentChange van IDynamicConceptProviderConcept
De methode NotifyParent op een dynamische conceptprovider is een callback die wordt uitgevoerd door het kerngegevensmodel wanneer een statische manipulatie van het individuele bovenliggende model van het object wordt gemaakt. Voor een gegeven bovenliggend model dat is toegevoegd, wordt deze methode een eerste keer aangeroepen wanneer dit bovenliggende model wordt toegevoegd en een tweede keer als/wanneer dit bovenliggende model wordt verwijderd.
NotifyDestruct van IDynamicConceptProviderConcept
De methode NotifyDestruct op een dynamische conceptprovider is een callback die wordt gemaakt door het kerngegevensmodel aan het begin van de vernietiging van het object dat een dynamische conceptprovider is. Het biedt extra opschoonmogelijkheden voor klanten die dit vereisen.
--
Zie ook
Dit onderwerp maakt deel uit van een reeks waarin de interfaces worden beschreven die toegankelijk zijn vanuit C++, hoe u deze kunt gebruiken om een C++-extensie voor foutopsporingsprogramma's te bouwen en hoe u andere gegevensmodelconstructies (bijvoorbeeld JavaScript of NatVis) gebruikt vanuit een C++-gegevensmodelextensie.
Overzicht van foutopsporingsprogrammagegevensmodel C++
C++-interfaces voor de debuggergegevensmodel
Gegevensmodel C++ objecten voor foutopsporingsprogramma
Gegevensmodel C++ aanvullende interfaces voor foutopsporingsprogramma