Debugger Data Model C++ の概念

このトピックでは、デバッガー C++ データ モデルの概念について説明します。

データ モデルの概念

データ モデル内の合成オブジェクトは、実質的に次の 2 つになります。

  • キー/値/メタデータタプルのディクショナリ。
  • データ モデルでサポートされる一連の概念 (インターフェイス)。 概念は、クライアントが (データ モデルではなく) 実装して、指定されたセマンティック動作のセットを提供するインターフェイスです。 現在サポートされている概念のセットを次に示します。
概念インターフェイス 説明
IDataModelConcept 概念は親モデルです。 このモデルが、登録された型シグネチャを介してネイティブ型に自動的にアタッチされる場合、その型の新しいオブジェクトがインスタンス化されるたびに、InitializeObject メソッドが自動的に呼び出されます。
IStringDisplayableConcept オブジェクトは、表示用に文字列に変換できます。
IIterableConcept オブジェクトはコンテナーであり、反復処理できます。
IIndexableConcept オブジェクトはコンテナーであり、1 次元以上でインデックス化 (ランダム アクセス経由でアクセス) できます。
IPreferredRuntimeTypeConcept オブジェクトは、そのオブジェクトから派生した型について基になる型システムが提供できる以上のことを理解しており、静的な型からランタイム型への変換を独自に処理できます。
IDynamicKeyProviderConcept オブジェクトはキーの動的プロバイダーであり、コア データ モデルからすべてのキー クエリを引き継ぐ必要があります。 このインターフェイスは、通常、JavaScript などの動的言語への移行手段として使用されます。
IDynamicConceptProviderConcept オブジェクトは概念の動的プロバイダーであり、コア データ モデルからすべての概念クエリを引き継ぐ必要があります。 このインターフェイスは、通常、JavaScript などの動的言語への移行手段として使用されます。

データ モデルの概念: IDataModelConcept

親モデルとして別のモデル オブジェクトにアタッチされているモデル オブジェクトは、データ モデルの概念を直接サポートする必要があります。 データ モデルの概念には、次のように定義されるインターフェイス IDataModelConcept のサポートが必要です。

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

データ モデルは、データ モデル マネージャーの RegisterModelForTypeSignature メソッドまたは RegisterExtensionForTypeSignature メソッドを介して、正規ビジュアライザーとして、または特定のネイティブ タイプの拡張機能として登録できます。 これらのメソッドのいずれかを介してモデルが登録されると、データ モデルは、登録で渡された署名とタイプが一致するネイティブ オブジェクトに親モデルとして自動的にアタッチされます。 その添付ファイルが自動的に作成される時点で、InitializeObject メソッドがデータ モデルで呼び出されます。 これには、インスタンス オブジェクト、添付ファイルの原因となった型署名、および型署名内のワイルドカードに一致する型インスタンスを (線形順序で) 生成する列挙子が渡されます。 データ モデルの実装では、このメソッド呼び出しを使用して、必要なキャッシュを初期化できます。

GetName

RegisterNamedModel メソッドを介して特定のデータ モデルが既定の名前で登録されている場合、登録されたデータ モデルの IDataModelConcept インターフェイスはこのメソッドからその名前を返す必要があります。 モデルを複数の名前で登録することは完全に正当であることに注意してください (ここでは既定のまたは最適な名前が返されるはずです)。 モデルには名前がまったく付けられていない場合があります (名前で登録されていない限り)。 このような状況では、GetName メソッドは E_NOTIMPL を返す必要があります。

文字列表示可能概念: IStringDisplayableConcept

表示目的で文字列変換を提供するオブジェクトは、IStringDisplayableConcept インターフェイスの実装を通じて文字列表示可能な概念を実装できます。 このインターフェイスは次のように定義されます。

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

ToDisplayString

ToDisplayString メソッドは、クライアントがオブジェクトを表示する文字列に変換するとき (コンソール、UI など) に呼び出されます。 このような文字列変換は、追加のプログラム操作の基礎として使用されるべきではありません。 文字列変換自体は、呼び出しに渡されるメタデータによって大きく影響される可能性があります。 文字列変換では、PreferredRadix キーと PreferredFormat キーを尊重するようあらゆる試みを行う必要があります。

Iterable の概念: IIterableConcept と IModelIterator

他のオブジェクトのコンテナであり、それらに含まれるオブジェクトを反復する機能を表現したいオブジェクトは、 IIterableConcept および IModelIterator インターフェイスの実装によって反復可能な概念をサポートできます。 反復可能な概念のサポートとインデックス可能な概念のサポートの間には非常に重要な関係があります。 含まれるオブジェクトへのランダム アクセスをサポートするオブジェクトは、反復可能な概念に加えてインデックス可能な概念もサポートできます。 この場合、反復処理される要素は、インデックス可能な概念に渡されたときに同じオブジェクトを参照する既定のインデックスも生成する必要があります。 この不変条件を満たさない場合、デバッグ ホストで未定義の動作が発生します。

IIterableConcept は次のように定義されます。

DECLARE_INTERFACE_(IIterableConcept, IUnknown)
{
    STDMETHOD(GetDefaultIndexDimensionality)(_In_ IModelObject* contextObject, _Out_ ULONG64* dimensionality) PURE;
    STDMETHOD(GetIterator)(_In_ IModelObject* contextObject, _Out_ IModelIterator** iterator) PURE;
}

IModelIterator の概念は次のように定義されます。

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 の GetDefaultIndexDimensionality

GetDefaultIndexDimensionality メソッドは、ディメンションの数を既定のインデックスに返します。 オブジェクトがインデックス付けできない場合、このメソッドは 0 を返し、成功する必要があります (S_OK)。 このメソッドからゼロ以外の値を返すオブジェクトは、次のようなプロトコル コントラクトのサポートを宣言しています。

  • オブジェクトは、IIndexableConcept のサポートを介してインデックス可能な概念をサポートします
  • 反復可能概念の GetIterator メソッドから返される IModelIterator の GetNext メソッドは、生成された要素ごとに一意のデフォルト インデックスを返します。 このようなインデックスには、次に示すようにディメンションの数が含まれます。
  • IModelIterator の GetNext メソッドから返されたインデックスをインデックス可能なコンセプト (IIndexableConcept) の GetAt メソッドに渡すと、GetNext が生成したのと同じオブジェクトが参照されます。 同じ値が返されます。

IIterableConcept の GetIterator

反復可能な概念の GetIterator メソッドは、オブジェクトの反復処理に使用できる反復子インターフェイスを返します。 返される反復子は、GetIterator メソッドに渡されたコンテキスト オブジェクトを記憶する必要があります。 反復子自体のメソッドには渡されません。

IModelIterator の Reset

反復可能概念から返された反復子の Reset メソッドは、反復子の位置を、反復子が最初に作成されたとき (最初の要素の前) の位置に戻します。 反復子で Reset メソッドをサポートすることを強くお勧めしますが、必須ではありません。 反復子は C++ 入力反復子に相当し、前方反復の 1 回のパスのみを許可できます。 このような場合、Reset メソッドは E_NOTIMPL で失敗する可能性があります。

IModelIterator の GetNext

GetNext メソッドは、反復子を前方に移動し、次に反復処理された要素をフェッチします。 オブジェクトが反復可能であることに加えてインデックスが作成可能であり、これが 0 以外の値を返す GetDefaultIndexDimensionality 引数によって示される場合、このメソッドはオプションで既定のインデックスを返して、インデクサーから生成された値に戻すことができます。 呼び出し元は 0/nullptr を渡して、インデックスを取得しないことを選択できることに注意してください。 呼び出し元が部分的なインデックス (例: GetDefault Index Dimensionality によって生成された数より小さい) を要求することは違反とみなされます。

反復子が正常に前方に移動したが、反復処理された要素の値を読み取る際にエラーが発生した場合、メソッドはエラー AND を返し、"object" にエラー オブジェクトを入力する可能性があります。 含まれる要素の反復の終了時に、反復子は GetNext メソッドから E_BOUNDS を返します。 後続の呼び出しも (Reset 呼び出しが介在しない限り) E_BOUNDS を返します。

Indexable の概念: IIndexableConcept

コンテンツのセットへのランダム アクセスを提供したいオブジェクトは、IIndexableConcept インターフェイスのサポートを通じてインデックス可能な概念をサポートできます。 インデックス可能なほとんどのオブジェクトは、反復可能な概念のサポートを通じて反復可能になります。 ただし、通常、これは必要ありません。 サポートされている場合は、反復子とインデクサーの間に重要な関係があります。 反復子は GetDefaultIndexDimensionality をサポートし、そのメソッドからゼロ以外の値を返し、そこに文書化されたコントラクトをサポートする必要があります。 インデクサーの概念インターフェイスは次のように定義されています。

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;
}

インデクサー (および反復子との相互作用) を使用する例を次に示します。 この例では、インデックス付け可能なコンテナーの内容を反復し、インデクサーを使用して、返されたばかりの値を取得します。 この操作は書かれているとおり機能的には役に立ちませんが、これらのインターフェイスがどのように相互作用するかを示しています。 次の例では、メモリ割り当てエラーは処理されないことに注意してください。 ここでは、new をスローすることを前提としています (これは、コードが存在する環境によっては不適切な前提となる可能性があります。データ モデルの COM メソッドは C++ 例外エスケープを持つことができません)。

ComPtr<IModelObject> spObject;

//
// Assume we have gotten some object in spObject that is iterable (e.g.: an object which represents a std::vector<SOMESTRUCT>)
//
ComPtr<IIterableConcept> spIterable;
ComPtr<IIndexableConcept> spIndexer;
if (SUCCEEDED(spObject->GetConcept(__uuidof(IIterableConcept), &spIterable, nullptr)) &&
    SUCCEEDED(spObject->GetConcept(__uuidof(IIndexableConcept), &spIndexable, nullptr)))
{
    ComPtr<IModelIterator> spIterator;

    //
    // Determine how many dimensions the default indexer is and allocate the requisite buffer.
    //
    ULONG64 dimensions;
    if (SUCCEEDED(spIterable->GetDefaultIndexDimensionality(spObject.Get(), &dimensions)) && dimensions > 0 &&
        SUCCEEDED(spIterable->GetIterator(spObject.Get(), &spIterator)))
    {
        std::unique_ptr<ComPtr<IModelObject>[]> spIndexers(new ComPtr<IModelObject>[dimensions]);

        //
        // We have an iterator.  Error codes have semantic meaning here.  E_BOUNDS indicates the end of iteration.  E_ABORT indicates that
        // the debugger host or application is trying to abort whatever operation is occurring.  Anything else indicates
        // some other error (e.g.: memory read failure) where the iterator MIGHT still produce values.
        //
        for(;;)
        {
            ComPtr<IModelObject> spContainedStruct;
            ComPtr<IKeyStore> spContainedMetadata;

            //
            // When we fetch the value from the iterator, it will pass back the default 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

GetDimensionality メソッドは、オブジェクトのインデックスが作成されるディメンションの数を返します。 オブジェクトが反復可能かつインデックス可能である場合、GetDefaultIndexDimensionality の実装は、インデクサーの次元数に関して GetDimensionality の実装と一致する必要があることに注意してください。

GetAt

GetAt メソッドは、インデックス付きオブジェクト内から特定の N 次元インデックスの値を取得します。 N 次元のインデクサー (N は GetDimensionality から返される値) がサポートされている必要があります。 オブジェクトは、異なるタイプによって異なるドメインでインデックス付けできる場合があることに注意してください (例: 序数と文字列の両方を介してインデックス付け可能)。 インデックスが範囲外の場合 (またはアクセスできなかった場合)、メソッドは失敗を返します。 ただし、そのような場合でも、出力オブジェクトはエラー オブジェクトに設定される可能性があります。

SetAt

SetAt メソッドは、インデックス付きオブジェクト内から特定の N 次元インデックスに値を設定しようとします。 N 次元のインデクサー (N は GetDimensionality から返される値) がサポートされている必要があります。 オブジェクトは、異なるタイプによって異なるドメインでインデックス付けできる場合があることに注意してください (例: 序数と文字列の両方を介してインデックス付け可能)。 一部のインデクサーは読み取り専用です。 このような場合、SetAt メソッドの呼び出しから E_NOTIMPL が返されます。

優先ランタイム型の概念: IPreferredRuntimeTypeConcept

デバッグ ホストにクエリを実行して、シンボリック情報にある静的型からオブジェクトの実際の実行時型を決定することを試みることができます。 この変換は、完全に正確な情報 (例: C++ RTTI) に基づく場合もあれば、オブジェクト内の仮想関数テーブルの形状などの強力なヒューリスティックに基づく場合もあります。 ただし、一部のオブジェクトは、デバッグ ホストのヒューリスティックに適合しないため、静的型からランタイム型に変換できません (例: RTTI または仮想関数テーブルがありません)。 このような場合、オブジェクトのデータ モデルは、デフォルトの動作をオーバーライドし、デバッグ ホストが理解できるよりもオブジェクトの「ランタイム タイプ」について詳しく知っていると宣言することを選択できます。 これは、優先ランタイム タイプの概念と IPreferredRuntimeTypeConcept インターフェイスのサポートを通じて行われます。

IPreferredRuntimeTypeConcept インターフェイスは次のように宣言されます。

DECLARE_INTERFACE_(IPreferredRuntimeTypeConcept, IUnknown)
{
    STDMETHOD(CastToPreferredRuntimeType)(_In_ IModelObject* contextObject, _COM_Errorptr_ IModelObject** object) PURE;
}

CastToPreferredRuntimeType

CastToPreferredRuntimeType メソッドは、クライアントが静的型インスタンスからそのインスタンスのランタイム型への変換を試みるたびに呼び出されます。 問題のオブジェクトが (アタッチされた親モデルの 1 つを通じて) 推奨されるランタイム型の概念をサポートしている場合、このメソッドが呼び出されて変換が実行されます。 このメソッドは、元のオブジェクトを返す (変換がないか分析できなかった)、ランタイム型の新しいインスタンスを返す、セマンティック以外の理由で失敗する (メモリ不足など)、または E_NOT_SET を返すかのいずれかを行う可能性があります。 E_NOT_SET エラー コードは、実装がデフォルトの動作をオーバーライドしたくないこと、およびデータ モデルがデバッグ ホストによって実行される分析 (例: RTTI 分析、 仮想関数テーブルの形状の検討など...)

動的プロバイダーの概念: IDynamicKeyProviderConcept と IDynamicConceptProviderConcept

通常、データ モデル自体はオブジェクトのキーと概念の管理を処理しますが、その概念が理想的ではない場合があります。 特に、クライアントがデータ モデルと他の真に動的なもの (例: JavaScript) との間にブリッジを作成したい場合、データ モデルの実装からキーとコンセプトの管理を引き継ぐことが有益な場合があります。 コア データ モデルは IModelObject の唯一の実装であるため、これは代わりに、動的キー プロバイダーの概念と動的コンセプト プロバイダーの概念という 2 つの概念の組み合わせによって行われます。 両方を実装するかどちらも実装しないのが一般的ですが、そのような要件はありません。

両方が実装されている場合は、動的キー プロバイダーの概念を動的概念プロバイダーの概念の前に追加する必要があります。 これらの概念はどちらも特別です。 これらはオブジェクトのスイッチを事実上切り替えて、オブジェクトを「静的管理」から「動的管理」に変更します。 これらの概念は、オブジェクトのデータ モデルによって管理されるキー/概念がない場合にのみ設定できます。 これらの概念がオブジェクトに追加されると、これを行う操作は取り消すことができません。

動的概念プロバイダーである IModelObject とそうでない IModelObject の間には、拡張性に関する追加のセマンティックの違いがあります。 これらの概念は、クライアントがデータ モデルと JavaScript などの動的言語システムの間にブリッジを作成できるようにすることを目的としています。 データ モデルには、JavaScript プロトタイプ チェーンのような線形チェーンではなく、親モデルのツリーが存在するという点で、JavaScript などのシステムとは根本的に異なる拡張性の概念があります。 このようなシステムとの関係を改善するために、動的概念プロバイダーである IModelObject には、単一のデータ モデルの親があります。 その単一データ モデルの親は通常の IModelObject であり、データ モデルの場合と同様に任意の数の親モデルを持つことができます。 親を追加または削除する動的概念プロバイダーへの要求は、自動的に単一の親にリダイレクトされます。 部外者の観点からは、動的概念プロバイダーには親モデルの通常のツリー スタイル チェーンがあるかのように見えます。 動的概念プロバイダー概念の実装者は、中間の単一の親を認識する唯一のオブジェクト (コア データ モデルの外部) です。 その単一の親を動的言語システムにリンクしてブリッジを提供できます (例: JavaScript プロトタイプ チェーンに配置)。

動的キー プロバイダーの概念は次のように定義されています。

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;
}

動的概念プロバイダーの概念は次のように定義されます。

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;
}

IDynamicKeyProviderConcept の GetKey

動的キー プロバイダーの GetKey メソッドは、主に IModelObject の GetKey メソッドをオーバーライドします。 動的キープロバイダーは、キーの値とそのキーに関連付けられたメタデータを返すことが期待されます。 キーが存在しない場合 (ただし、他のエラーは発生しない)、プロバイダーは hasKey パラメーターで false を返し、S_OK で成功する必要があります。 この呼び出しに失敗すると、キーの取得に失敗したとみなされ、親モデル チェーンを介したキーの検索が明示的に停止されます。 hasKey で false を返し、成功するとキーの検索が続行されます。 GetKey がボックス化されたプロパティ アクセサーをキーとして返すのは、完全に有効であることに注意してください。 これは、プロパティ アクセサーを返す IModelObject の GetKey メソッドと意味的に同じです。

IDynamicKeyProviderConcept の SetKey

動的キー プロバイダーの SetKey メソッドは、事実上、IModelObject の SetKey メソッドをオーバーライドします。 これにより、動的プロバイダーにキーが設定されます。 これは、実質的にプロバイダーで新しいプロパティを作成することです。 Expando プロパティの作成などの概念をサポートしていないプロバイダーは、ここで E_NOTIMPL を返す必要があることに注意してください。

IDynamicKeyProviderConcept の EnumerateKeys

動的キー プロバイダーの EnumerateKeys メソッドは、事実上、IModelObject の EnumerateKeys メソッドのオーバーライドです。 これにより、動的プロバイダー内のすべてのキーが列挙されます。 返される列挙子には、実装で遵守する必要があるいくつかの制限があります。

  • これは、EnumerateKeyValues や EnumerateKeyReferences ではなく、EnumerateKeys の呼び出しとして動作する必要があります。 基になるプロパティ アクセサーを解決せずにキー値を返す必要があります (そのような概念がプロバイダーに存在する場合)。
  • 単一の動的キープロバイダーの観点からは、物理的に異なるキーである同じ名前の複数のキーを列挙することは違法です。 これは、親モデル チェーンを通じて接続されているさまざまなプロバイダーで発生する可能性がありますが、単一プロバイダーの観点からは発生しません。

IDynamicConceptProviderConcept の GetConcept

動的コンセプト プロバイダーの GetConcept メソッドは、事実上、IModelObject の GetConcept メソッドをオーバーライドします。 動的概念プロバイダーは、クエリされた概念が存在する場合は、その概念のインターフェイスと、その概念に関連付けられたメタデータを返す必要があります。 コンセプトがプロバイダーに存在しない場合は、hasConcept 引数で返される false 値と正常な戻りによってそれを示す必要があります。 このメソッドが失敗すると、概念の取得に失敗したことになり、概念の検索が明示的に停止されます。 hasConcept に対して false を返し、コードが成功すると、親モデル ツリーを通じてコンセプトの検索が続行されます。

IDynamicConceptProviderConcept の SetConcept

動的コンセプト プロバイダーの SetConcept メソッドは、事実上、IModelObject の SetConcept メソッドをオーバーライドします。 動的プロバイダーによって概念が割り当てられます。 これにより、オブジェクトが反復可能、インデックス可能、文字列変換可能などになる可能性があります。概念の作成を許可しないプロバイダーは、ここで E_NOPTIMPL を返す必要があることに注意してください。

IDynamicConceptProviderConcept の NotifyParent

動的コンセプト プロバイダーに対する NotifyParent 呼び出しは、データ モデルの「複数の親モデル」パラダイムをより動的言語にブリッジできるように作成された単一親モデルを動的プロバイダーに通知するために、コア データ モデルによって使用されます。 その単一の親モデルを操作すると、動的プロバイダーへのさらなる通知が発生します。 このコールバックは、動的コンセプトプロバイダーコンセプトの割り当て直後に行われることに注意してください。

IDynamicConceptProviderConcept の NotifyParentChange

動的コンセプト プロバイダーの NotifyParent メソッドは、オブジェクトの単一親モデルの静的操作が行われたときに、コア データ モデルによって行われるコールバックです。 追加された任意の親モデルについて、このメソッドは、親モデルが追加されたときに初めて呼び出され、親モデルが削除された場合に 2 回目に呼び出されます。

IDynamicConceptProviderConcept の NotifyDestruct

動的コンセプト プロバイダーの NotifyDestruct メソッドは、動的コンセプト プロバイダーであるオブジェクトの破棄の開始時にコア データ モデルによって作成されるコールバックです。 これは、それを必要とするクライアントに追加のクリーン機会を提供します。

--

関連項目

このトピックは、C++ からアクセスできるインターフェイス、それらを使用して C++ ベースのデバッガー拡張機能を構築する方法、および C++ データ モデル拡張機能から他のデータ モデル構造 (JavaScript や NatVis など) を利用する方法を説明するシリーズの一部です。

Debugger Data Model C++ の概要

Debugger Data Model C++ のインターフェイス

Debugger Data Model C++ のオブジェクト

Debugger Data Model C++ のその他のインターフェイス

Debugger Data Model C++ の概念

Debugger Data Model C++ のスクリプト