디버거 데이터 모델 C++ 개념
이 항목에서는 디버거 C++ 데이터 모델의 개념에 대해 설명합니다.
데이터 모델의 개념
데이터 모델의 가상 개체는 사실상 다음 두 가지입니다.
- 키/값/메타데이터 튜플의 사전입니다.
- 데이터 모델에서 지원하는 개념(인터페이스) 집합입니다. 개념은 지정된 의미 체계 동작 집합을 제공하기 위해 클라이언트(데이터 모델과 반대)가 구현하는 인터페이스입니다. 현재 지원되는 개념 집합이 여기에 나열되어 있습니다.
개념 인터페이스 | 설명 |
---|---|
IDataModelConcept | 개념은 부모 모델입니다. 이 모델이 등록된 형식 서명을 통해 네이티브 형식에 자동으로 연결되면 이러한 형식의 새 개체가 인스턴스화될 때마다 InitializeObject 메서드가 자동으로 호출됩니다. |
IStringDisplayableConcept | 표시를 위해 개체를 문자열로 변환할 수 있습니다. |
IIterableConcept | 개체는 컨테이너이며 반복할 수 있습니다. |
IIndexableConcept | 개체는 컨테이너이며 하나 이상의 차원에서 인덱싱(임의 액세스를 통해 액세스)할 수 있습니다. |
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;
}
데이터 모델은 정식 시각화 도우미로 등록하거나 데이터 모델 관리자의 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 메서드는 클라이언트가 표시할 문자열(콘솔, UI 등)으로 개체를 변환하려고 할 때마다 호출됩니다. 이러한 문자열 변환은 추가 프로그래밍 방식 조작을 기반으로 사용하면 안 됩니다. 문자열 변환 자체는 호출에 전달된 메타데이터의 영향을 크게 받을 수 있습니다. 문자열 변환은 PreferredRadix 및 PreferredFormat 키를 적용하기 위해 모든 시도를 수행해야 합니다.
반복 가능한 개념: 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)해야 합니다. 이 메서드에서 0이 아닌 값을 반환하는 모든 개체는 다음을 나타내는 프로토콜 계약에 대한 지원을 선언합니다.
- 개체는 IIndexableConcept 지원을 통해 인덱싱 가능한 개념을 지원합니다.
- 반복 가능한 개념의 GetIterator 메서드에서 반환된 IModelIterator의 GetNext 메서드는 생성된 각 요소에 대해 고유한 기본 인덱스를 반환합니다. 이러한 인덱스에는 여기에 표시된 차원 수가 있습니다.
- IModelIterator의 GetNext 메서드에서 반환된 인덱스를 인덱싱 가능한 개념(IIndexableConcept)의 GetAt 메서드에 전달하면 GetNext에서 생성한 것과 동일한 개체가 참조됩니다. 동일한 값이 반환됩니다.
IIterableConcept의 GetIterator
반복 가능한 개념의 GetIterator 메서드는 개체를 반복하는 데 사용할 수 있는 반복기 인터페이스를 반환합니다. 반환된 반복기는 GetIterator 메서드에 전달된 컨텍스트 개체를 기억해야 합니다. 반복기 자체의 메서드에 전달되지 않습니다.
IModelIterator의 재설정
반복 가능한 개념에서 반환된 반복기의 Reset 메서드는 반복기가 처음 만들어진 위치(첫 번째 요소 이전)로 반복기의 위치를 복원합니다. 반복기가 Reset 메서드를 지원하는 것이 좋지만 필수는 아닙니다. 반복기는 C++ 입력 반복기와 동일할 수 있으며 한 번의 전달 반복만 허용합니다. 이 경우 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;
}
인덱서(및 반복기와의 상호 작용)를 사용하는 예제는 다음과 같습니다. 다음은 인덱싱 가능한 컨테이너의 내용을 반복하고 인덱서에서 방금 반환된 값으로 돌아가는 예제입니다. 이 작업은 기록된 것처럼 기능적으로 쓸모가 없지만 이러한 인터페이스가 상호 작용하는 방법을 보여 줍니다. 아래 예제에서는 메모리 할당 오류를 처리하지 않습니다. 새로 throw된다고 가정합니다(코드가 존재하는 환경에 따라 가정이 좋지 않을 수 있음- 데이터 모델의 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 메서드는 개체가 인덱싱되는 차원 수를 반환합니다. 개체가 반복 가능하고 인덱싱 가능한 경우 GetDefaultIndexDimensionality 구현은 인덱서에 있는 차원 수에 대한 GetDimensionality 구현에 동의해야 합니다.
GetAt 메서드는 인덱싱된 개체 내에서 특정 N차원 인덱스의 값을 검색합니다. N이 GetDimensionality에서 반환된 값인 N 차원의 인덱서는 지원되어야 합니다. 개체는 서로 다른 형식(예: 서수 및 문자열을 통해 인덱싱 가능)에 따라 다른 do기본s에서 인덱싱할 수 있습니다. 인덱스가 범위를 벗어났거나 액세스할 수 없는 경우 메서드는 오류를 반환합니다. 그러나 이러한 경우 출력 개체는 여전히 오류 개체로 설정될 수 있습니다.
SetAt 메서드는 인덱싱된 개체 내에서 특정 N차원 인덱스의 값을 설정하려고 시도합니다. N이 GetDimensionality에서 반환된 값인 N 차원의 인덱서는 지원되어야 합니다. 개체는 서로 다른 형식(예: 서수 및 문자열을 통해 인덱싱 가능)에 따라 다른 do기본s에서 인덱싱할 수 있습니다. 일부 인덱서는 읽기 전용입니다. 이러한 경우 setAt 메서드에 대한 모든 호출에서 E_NOTIMPL 반환됩니다.
기본 런타임 형식 개념: IPreferredRuntimeTypeConcept
디버그 호스트를 쿼리하여 기호 정보에 있는 정적 형식에서 개체의 실제 런타임 형식을 확인할 수 있습니다. 이 변환은 완전히 정확한 정보(예: C++ RTTI)를 기반으로 하거나 개체 내의 가상 함수 테이블의 모양과 같은 강력한 추론을 기반으로 할 수 있습니다. 그러나 일부 개체는 디버그 호스트의 추론에 맞지 않으므로 정적 형식에서 런타임 형식으로 변환할 수 없습니다(예: RTTI 또는 가상 함수 테이블이 없음). 이러한 경우 개체의 데이터 모델은 기본 동작을 재정의하고 디버그 호스트가 이해할 수 있는 것보다 개체의 "런타임 형식"에 대해 더 많이 알고 있음을 선언하도록 선택할 수 있습니다. 이 작업은 기본 설정 런타임 형식 개념 및 IPreferredRuntimeTypeConcept 인터페이스의 지원을 통해 수행됩니다.
IPreferredRuntimeTypeConcept 인터페이스는 다음과 같이 선언됩니다.
DECLARE_INTERFACE_(IPreferredRuntimeTypeConcept, IUnknown)
{
STDMETHOD(CastToPreferredRuntimeType)(_In_ IModelObject* contextObject, _COM_Errorptr_ IModelObject** object) PURE;
}
CastToPreferredRuntimeType 메서드는 클라이언트가 정적 형식 인스턴스에서 해당 인스턴스의 런타임 형식으로 변환하려고 할 때마다 호출됩니다. 해당 개체가 기본 설정 런타임 형식 개념을 지원하는 경우(연결된 부모 모델 중 하나를 통해) 변환을 수행하기 위해 이 메서드가 호출됩니다. 이 메서드는 원래 개체를 반환하거나(변환이 없거나 분석할 수 없음) 런타임 형식의 새 인스턴스를 반환하거나, 의미 체계가 아닌 이유(예: 메모리 부족)로 인해 실패하거나, E_NOT_SET 반환할 수 있습니다. E_NOT_SET 오류 코드는 구현이 기본 동작을 재정의하지 않고 데이터 모델이 디버그 호스트에서 수행하는 분석(예: RTTI 분석, 가상 함수 테이블의 모양 검사)으로 대체되어야 했음을 데이터 모델에 나타내는 매우 특별한 오류 코드입니다. etc...)
동적 공급자 개념: IDynamicKeyProviderConcept 및 IDynamicConceptProviderConcept
데이터 모델 자체는 일반적으로 개체에 대한 키 및 개념 관리를 처리하지만 해당 개념이 이상적이지 않은 경우가 있습니다. 특히 클라이언트가 데이터 모델과 실제로 동적인 다른 항목(예: JavaScript) 사이에 브리지를 만들려는 경우 데이터 모델의 구현에서 키 및 개념 관리를 인수하는 것이 중요할 수 있습니다. 핵심 데이터 모델은 IModelObject의 유일한 구현이므로 동적 키 공급자 개념과 동적 개념 공급자 개념이라는 두 가지 개념의 조합을 통해 수행됩니다. 둘 다 또는 둘 다 구현하는 것이 일반적이지만 이러한 요구 사항은 없습니다.
둘 다 구현되는 경우 동적 개념 공급자 개념 앞에 동적 키 공급자 개념을 추가해야 합니다. 이 두 가지 개념은 모두 특별합니다. 개체를 "정적으로 관리"에서 "동적으로 관리"로 변경하는 스위치를 효과적으로 전환합니다. 이러한 개념은 개체의 데이터 모델에서 관리하는 키/개념이 없는 경우에만 설정할 수 있습니다. 이러한 개념이 개체에 추가되면 이 작업을 수행하는 작업은 취소할 수 없습니다.
동적 개념 공급자인 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가 boxed 속성 접근자를 키로 반환하는 것은 완벽하게 합법적입니다. 이는 속성 접근자를 반환하는 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 메서드는 개체의 단일 부모 모델을 정적 조작할 때 핵심 데이터 모델에서 만든 콜백입니다. 추가된 모든 부모 모델의 경우 이 메서드는 부모 모델이 추가될 때 처음으로 호출되고, 부모 모델이 제거되면 두 번째로 호출됩니다.
IDynamicConceptProviderConcept의 NotifyDestruct
동적 개념 공급자의 NotifyDestruct 메서드는 동적 개념 공급자인 개체가 소멸될 때 핵심 데이터 모델에서 만든 콜백입니다. 필요한 클라이언트에 추가 클린 기회를 제공합니다.
--
참고 항목
이 항목은 C++에서 액세스할 수 있는 인터페이스, 이를 사용하여 C++ 기반 디버거 확장을 빌드하는 방법 및 C++ 데이터 모델 확장에서 다른 데이터 모델 구문(예: JavaScript 또는 NatVis)을 사용하는 방법을 설명하는 시리즈의 일부입니다.