このトピックでは、デバッガー C++ データ モデルの概念について説明します。
データ モデルの概念
データ モデル内の合成オブジェクトは、実質的に次の 2 つになります。
- キー/値/メタデータタプルのディクショナリ。
- データ モデルでサポートされる一連の概念 (インターフェイス)。 概念は、クライアントが (データ モデルではなく) 実装して、指定されたセマンティック動作のセットを提供するインターフェイスです。 現在サポートされている概念のセットを次に示します。
概念インターフェイス | 説明 |
---|---|
IDataModelConcept | 概念は親モデルです。 このモデルが登録済みの型シグネチャを介してネイティブ型に自動的にアタッチされる場合、InitializeObject メソッドは、そのような型の新しいオブジェクトがインスタンス化されるたびに自動的に呼び出されます。 |
IStringDisplayableConcept(文字列表示可能な概念) | オブジェクトは、表示目的で文字列に変換できます。 |
IIterableConcept | オブジェクトはコンテナーであり、反復処理できます。 |
IIndexableConcept | オブジェクトはコンテナーであり、1 つ以上のディメンションでインデックスを作成 (ランダム アクセス経由でアクセス) できます。 |
望ましいランタイムタイプ概念 | オブジェクトは、基になる型システムが提供可能であり、静的からランタイム型への独自の変換を処理するよりも、そこから派生した型について理解します。 |
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;
}
データ モデルは、データ モデル マネージャーの RegisterModelForTypeSignature メソッドまたは RegisterExtensionForTypeSignature メソッドを使用して、正規ビジュアライザーとして、または特定のネイティブ型の拡張機能として登録できます。 これらのメソッドのいずれかを使用してモデルを登録すると、データ モデルは、登録で渡されたシグネチャと一致する型を持つ任意のネイティブ オブジェクトに親モデルとして自動的にアタッチされます。 その添付ファイルが自動的に作成される時点で、InitializeObject メソッドがデータ モデルで呼び出されます。 インスタンス オブジェクト、添付ファイルの原因となった型シグネチャ、および型シグネチャ内のワイルドカードと一致する型インスタンスを (線形順に) 生成する列挙子が渡されます。 データ モデルの実装では、このメソッド呼び出しを使用して、必要なキャッシュを初期化できます。
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 インターフェイスの実装によって反復可能な概念をサポートできます。 iterable 概念のサポートとインデックス可能な概念のサポートの間には、非常に重要な関係があります。 含まれているオブジェクトへのランダム アクセスをサポートするオブジェクトは、iterable の概念に加えて、インデックス可能な概念をサポートできます。 この場合、反復処理された要素は、インデックス可能な概念に渡されたときに同じオブジェクトを参照する既定のインデックスも生成する必要があります。 この不変性を満たさなくなると、デバッグ ホストで未定義の動作が発生します。
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)。 このメソッドから 0 以外の値を返すオブジェクトは、次の状態のプロトコル コントラクトのサポートを宣言しています。
- オブジェクトは、IIndexableConcept のサポートを介してインデックス可能な概念をサポートします
- Iterable 概念の GetIterator メソッドから返される IModelIterator の GetNext メソッドは、生成された各要素の一意の既定のインデックスを返します。 このようなインデックスには、次に示すようにディメンションの数が含まれます。
- IModelIterator の GetNext メソッドから返されたインデックスを、インデックス可能な概念 (IIndexableConcept) の GetAt メソッドに渡すと、GetNext が生成したのと同じオブジェクトが参照されます。 同じ値が返されます。
IIterableConcept の GetIterator
反復可能な概念の GetIterator メソッドは、オブジェクトの反復処理に使用できる反復子インターフェイスを返します。 返される反復子は、GetIterator メソッドに渡されたコンテキスト オブジェクトを記憶する必要があります。 反復子自体のメソッドには渡されません。
IModelIterator の リセット
反復可能な概念から返される反復子の Reset メソッドは、反復子が最初に作成されたとき (最初の要素の前) に反復子の位置を復元します。 反復子で Reset メソッドをサポートすることを強くお勧めしますが、必須ではありません。 反復子は C++ 入力反復子に相当し、前方反復の 1 回のパスのみを許可できます。 このような場合、Reset メソッドはE_NOTIMPLで失敗する可能性があります。
IModelIterator の GetNext
GetNext メソッドは、反復子を前方に移動し、次に反復処理された要素をフェッチします。 オブジェクトが読み取り可能であるだけでなく、インデックスが作成可能であり、これが 0 以外の値を返す GetDefaultIndexDimensionality 引数によって示される場合、このメソッドは必要に応じて、インデクサーから生成された値に戻す既定のインデックスを返す可能性があります。 呼び出し元は 0/nullptr を渡し、インデックスを取得しないことを選択できます。 呼び出し元が部分的なインデックスを要求することは違法と見なされます (例: GetDefaultIndexDimensionality によって生成された数より小さい)。
反復子が正常に前方に移動したが、反復処理された要素の値を読み取る際にエラーが発生した場合、メソッドはエラー エラーを返し、"object" にエラー オブジェクト 埋め込む可能性があります。 含まれている要素の反復処理の終了時に、反復子は GetNext メソッドからE_BOUNDSを返します。 それ以降の呼び出し (介入リセット呼び出しがない限り) もE_BOUNDS返されます。
インデックス可能概念: IIndexableConcept
コンテンツのセットへのランダム アクセスを提供するオブジェクトは、IIndexableConcept インターフェイスのサポートを介してインデックス可能な概念をサポートできます。 インデックス可能なほとんどのオブジェクトは、反復可能な概念のサポートを通じて反復可能になります。 ただし、これは必須ではありません。 サポートされている場合は、反復子とインデクサーの間に重要な関係があります。 反復子は GetDefaultIndexDimensionality をサポートし、そのメソッドから 0 以外の値を返し、そこに記載されているコントラクトをサポートする必要があります。 インデクサーの概念インターフェイスは次のように定義されています。
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;
}
インデクサー (および反復子との相互作用) を使用する例を次に示します。 この例では、インデックス可能なコンテナーの内容を反復処理し、インデクサーを使用して、返された値に戻ります。 この操作は、記述されているように機能的には役に立ちませんが、これらのインターフェイスがどのように相互作用するかを示しています。 次の例では、メモリ割り当てエラーは処理されないことに注意してください。 これは新しい例外のスローを想定しており、コードが存在する環境によっては、データモデルの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 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.
//
}
}
}
}
GetDimensionality の
GetDimensionality メソッドは、オブジェクトのインデックスが作成されるディメンションの数を返します。 オブジェクトが iterable と indexable の両方である場合、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 メソッドは、クライアントが静的型インスタンスからそのインスタンスのランタイム型に変換しようとするたびに呼び出されます。 問題のオブジェクトが (アタッチされた親モデルの 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 と success で false を返すと、キーの検索が続行されます。 GetKey がボックス化されたプロパティ アクセサーをキーとして返すのは完全に有効であることに注意してください。 これは、プロパティ アクセサーを返す IModelObject の GetKey メソッドと意味的に同じです。
IDynamicKeyProviderConcept の SetKey
動的キー プロバイダーの SetKey メソッドは、実質的に IModelObject の SetKey メソッドのオーバーライドです。 これにより、動的プロバイダーにキーが設定されます。 これは、実質的にプロバイダーで新しいプロパティを作成することです。 expando プロパティの作成などの概念をサポートしていないプロバイダーは、ここでE_NOTIMPL返されることに注意してください。
IDynamicKeyProviderConcept の EnumerateKeys
動的キー プロバイダーの EnumerateKeys メソッドは、実質的に IModelObject の EnumerateKeys メソッドのオーバーライドです。 これにより、動的プロバイダー内のすべてのキーが列挙されます。 返される列挙子には、実装で受け入れなければならないいくつかの制限があります。
- EnumerateKeyValues または EnumerateKeyReferences ではなく、EnumerateKeys の呼び出しとして動作する必要があります。 基になるプロパティ アクセサーを解決しないキー値を返す必要があります (このような概念がプロバイダーに存在する場合)。
- 1 つの動的キー プロバイダーの観点からは、物理的に異なるキーである同じ名前の複数のキーを列挙することは無効です。 これは、親モデル チェーンを介してアタッチされているさまざまなプロバイダーで発生する可能性がありますが、1 つのプロバイダーの観点からは発生することはできません。
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 など) を使用する方法について説明するシリーズの一部です。