Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tema se describen los conceptos del modelo de datos de C++ del depurador.
Conceptos del modelo de datos
Los objetos sintéticos del modelo de datos son realmente dos cosas:
- Diccionario de tuplas clave/valor/metadatos.
- Un conjunto de conceptos (interfaces) compatibles con el modelo de datos. Los conceptos son interfaces que un cliente (en lugar del modelo de datos) implementa para proporcionar un conjunto especificado de comportamiento semántico. Aquí se enumeran los conjuntos de conceptos admitidos actualmente.
| Interfaz de Concepto | Descripción |
|---|---|
| IDataModelConcept | El concepto es un modelo primario. Si este modelo se adjunta automáticamente a un tipo nativo a través de una firma de tipo registrado, se llamará automáticamente al método InitializeObject cada vez que se cree una instancia de un nuevo objeto de este tipo. |
| IStringDisplayableConcept | El objeto se puede convertir en una cadena con fines de visualización. |
| IIterableConcept | El objeto es un contenedor y se puede iterar. |
| IIndexableConcept | El objeto es un contenedor y se puede indexar (al que se accede a través del acceso aleatorio) en una o varias dimensiones. |
| IPreferredRuntimeTypeConcept | El objeto entiende más sobre los tipos derivados de él que el sistema de tipos subyacente es capaz de proporcionar y desea controlar sus propias conversiones de tipo estático a en tiempo de ejecución. |
| IDynamicKeyProviderConcept | El objeto es un proveedor dinámico de claves y desea asumir todas las consultas de clave del modelo de datos principal. Esta interfaz se usa normalmente como puente a lenguajes dinámicos como JavaScript. |
| IDynamicConceptProviderConcept | El objeto es un proveedor dinámico de conceptos y desea asumir todas las consultas de concepto del modelo de datos principal. Esta interfaz se usa normalmente como puente a lenguajes dinámicos como JavaScript. |
El concepto del modelo de datos: IDataModelConcept
Cualquier objeto de modelo que esté asociado a otro objeto de modelo como modelo primario debe admitir directamente el concepto del modelo de datos. El concepto del modelo de datos requiere compatibilidad con una interfaz, IDataModelConcept definida como se indica a continuación.
DECLARE_INTERFACE_(IDataModelConcept, IUnknown)
{
STDMETHOD(InitializeObject)(_In_ IModelObject* modelObject, _In_opt_ IDebugHostTypeSignature* matchingTypeSignature, _In_opt_ IDebugHostSymbolEnumerator* wildcardMatches) PURE;
STDMETHOD(GetName)(_Out_ BSTR* modelName) PURE;
}
Un modelo de datos se puede registrar como visualizador canónico o como una extensión para un tipo nativo determinado a través de los métodos RegisterModelForTypeSignature o RegisterExtensionForTypeSignature del administrador de modelos de datos. Cuando se registra un modelo a través de cualquiera de estos métodos, el modelo de datos se adjunta automáticamente como modelo primario a cualquier objeto nativo cuyo tipo coincida con la firma pasada en el registro. En el punto en el que se realiza automáticamente ese archivo adjunto, se llama al método InitializeObject en el modelo de datos. Se pasa el objeto de instancia, la firma de tipo que provocó los datos adjuntos y un enumerador que genera las instancias de tipo (en orden lineal) que coinciden con los caracteres comodín de la firma de tipo. La implementación del modelo de datos puede usar esta llamada al método para inicializar las memorias caché que requiera.
Si un modelo de datos determinado se registra con un nombre predeterminado a través del método RegisterNamedModel, la interfaz IDataModelConcept del modelo de datos registrado debe devolver ese nombre de este método. Tenga en cuenta que es perfectamente legítimo que un modelo se registre con varios nombres (el valor predeterminado o el mejor debe devolverse aquí). Un modelo puede ser completamente sin nombre (siempre y cuando no esté registrado bajo un nombre). En tales circunstancias, el método GetName debe devolver E_NOTIMPL.
El Concepto de Cadena Mostrable: IStringDisplayableConcept
Un objeto que desea proporcionar una conversión de cadena con fines de visualización puede implementar el concepto que se puede mostrar de cadena mediante la implementación de la interfaz IStringDisplayableConcept. La interfaz se define de la siguiente manera:
DECLARE_INTERFACE_(IStringDisplayableConcept, IUnknown)
{
STDMETHOD(ToDisplayString)(_In_ IModelObject* contextObject, _In_opt_ IKeyStore* metadata, _Out_ BSTR* displayString) PURE;
}
Se llama al método ToDisplayString siempre que un cliente desea convertir un objeto en una cadena que se va a mostrar (en la consola, en la interfaz de usuario, etc.). Esta conversión de cadena no se debe usar para la base de la manipulación mediante programación adicional. La propia conversión de cadena puede estar profundamente influenciada por los metadatos pasados a la llamada. Una conversión de cadena debe realizar todos los intentos de respetar las claves PreferredRadix y PreferredFormat.
El concepto iterable: IIterableConcept e IModelIterator
Un objeto que es un contenedor de otros objetos y desea expresar la capacidad de iterar sobre esos objetos contenidos puede admitir el concepto iterable mediante una implementación de las interfaces IIterableConcept e IModelIterator. Existe una relación muy importante entre el soporte del concepto iterable y la compatibilidad del concepto indizable. Un objeto que admite el acceso aleatorio a los objetos contenidos puede admitir el concepto indizable además del concepto iterable. En este caso, los elementos iterados también deben generar un índice predeterminado que, cuando se pasa al concepto indexable, hacen referencia al mismo objeto. Si no se cumple esta invariable, se producirá un comportamiento indefinido en el host de depuración.
IIterableConcept se define de la siguiente manera:
DECLARE_INTERFACE_(IIterableConcept, IUnknown)
{
STDMETHOD(GetDefaultIndexDimensionality)(_In_ IModelObject* contextObject, _Out_ ULONG64* dimensionality) PURE;
STDMETHOD(GetIterator)(_In_ IModelObject* contextObject, _Out_ IModelIterator** iterator) PURE;
}
El concepto de IModelIterator se define de la siguiente manera:
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 de IIterableConcept
El método GetDefaultIndexDimensionality devuelve el número de dimensiones al índice predeterminado. Si un objeto no es indexable, este método debe devolver 0 y correcto (S_OK). Cualquier objeto que devuelva un valor distinto de cero de este método declara la compatibilidad con un contrato de protocolo que indica:
- El objeto admite el concepto indexable mediante la compatibilidad de IIndexableConcept
- El método GetNext del IModelIterator devuelto por el método GetIterator del concepto iterable devolverá un índice predeterminado único para cada elemento generado. Este índice tendrá el número de dimensiones como se indica aquí.
- Pasar los índices devueltos desde el método GetNext del IModelIterator al método GetAt en el concepto indexable (IIndexableConcept) hará referencia al mismo objeto generado por GetNext. Se devuelve el mismo valor.
GetIterator de IIterableConcept
El método GetIterator del concepto iterable devuelve una interfaz de iterador que se puede usar para iterar el objeto. El iterador devuelto debe recordar el objeto de contexto que se pasó al método GetIterator. No se pasará a los métodos en el propio iterador.
IModelIterator's Reset
El método Reset en un iterador devuelto desde el concepto iterable restaurará la posición del iterador a donde se creó por primera vez el iterador (antes del primer elemento). Aunque se recomienda encarecidamente que el iterador admita el método Reset, no es necesario. Un iterador puede ser el equivalente de un iterador de entrada de C++ y solo permitir un solo paso de iteración hacia delante. En tal caso, el método Reset puede producir un error con E_NOTIMPL.
GetNext de IModelIterator
El método GetNext mueve el iterador hacia delante y captura el siguiente elemento iterado. Si el objeto se puede indexar además de ser iterable y esto se indica mediante el argumento GetDefaultIndexDimensionality que devuelve un valor distinto de cero, este método puede devolver opcionalmente los índices predeterminados para volver al valor generado del indexador. Tenga en cuenta que un autor de llamada puede optar por pasar 0/nullptr y no recuperar ningún índice. Se considera ilegal que el autor de la llamada solicite índices parciales (por ejemplo: menor que el número generado por GetDefaultIndexDimensionality).
Si el iterador avanza con éxito, pero se produce un error al leer el valor del elemento iterado, el método puede devolver un error Y llenar "objeto" con un objeto de error. Al final de la iteración de los elementos contenidos, el iterador devolverá E_BOUNDS del método GetNext. Cualquier llamada posterior (a menos que haya habido una llamada de restablecimiento intermedio) también devolverá E_BOUNDS.
El concepto indexable: IIndexableConcept
Un objeto que desea proporcionar acceso aleatorio a un conjunto de contenido puede admitir el concepto indizable a través de la compatibilidad con la interfaz IIndexableConcept. La mayoría de los objetos indexables también serán iterables gracias al apoyo del concepto iterable. Sin embargo, esto no es necesario. Si se admite, hay una relación importante entre el iterador y el indexador. El iterador debe ser compatible con el método GetDefaultIndexDimensionality, devolver un valor distinto de cero de dicho método y cumplir con el contrato documentado en dicho lugar. La interfaz de concepto del indexador se define de la siguiente manera:
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;
}
A continuación se muestra un ejemplo de uso del indexador (y su interacción con el iterador). En este ejemplo se recorre en iteración el contenido de un contenedor indexable y se usa el indexador para volver al valor que se acaba de devolver. Aunque esa operación es funcionalmente inútil como se escribe, muestra cómo interactúan estas interfaces. Tenga en cuenta que el ejemplo siguiente no trata el error de asignación de memoria. Se supone que se produce un nuevo lanzamiento (que podría ser una suposición deficiente en función del entorno en el que existe el código: los métodos COM del modelo de datos no pueden tener escape de excepciones de 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.
//
}
}
}
}
El método GetDimensionality devuelve el número de dimensiones en las que se indexa el objeto. Tenga en cuenta que si el objeto es iterable e indizable, la implementación de GetDefaultIndexDimensionality debe estar de acuerdo con la implementación de GetDimensionality en cuanto a cuántas dimensiones tiene el indexador.
El método GetAt recupera el valor en un índice N dimensional determinado desde dentro del objeto indizado. Se debe admitir un indexador de N dimensiones donde N es el valor devuelto de GetDimensionality. Tenga en cuenta que un objeto puede ser indizable en dominios diferentes por tipos diferentes (por ejemplo: indizable a través de ordinales y cadenas). Si el índice está fuera del intervalo (o no se puede acceder a él), el método devolverá un error; sin embargo, en tales casos, el objeto de salida todavía se puede establecer en un objeto de error.
El método SetAt intenta establecer el valor en un índice N dimensional determinado desde dentro del objeto indizado. Se debe admitir un indexador de N dimensiones donde N es el valor devuelto de GetDimensionality. Tenga en cuenta que un objeto puede ser indizable en dominios diferentes por tipos diferentes (por ejemplo: indizable a través de ordinales y cadenas). Algunos indexadores son de solo lectura. En tales casos, se devolverá E_NOTIMPL desde cualquier llamada al método SetAt.
El concepto de tipo de tiempo de ejecución preferido: IPreferredRuntimeTypeConcept
Se puede consultar un host de depuración para intentar determinar el tipo en tiempo de ejecución real de un objeto de un tipo estático que se encuentra en información simbólica. Esta conversión puede basarse en información completamente precisa (por ejemplo: C++ RTTI) o puede basarse en heurística fuerte, como la forma de cualquier tabla de funciones virtuales dentro del objeto. Sin embargo, algunos objetos no se pueden convertir de un tipo estático a un tipo en tiempo de ejecución porque no caben en la heurística del host de depuración (por ejemplo, no tienen tablas de funciones RTTI ni virtuales). En tales casos, un modelo de datos para un objeto puede optar por invalidar el comportamiento predeterminado y declarar que sabe más sobre el "tipo en tiempo de ejecución" de un objeto que el host de depuración es capaz de comprender. Esto se hace a través del concepto de tipo en tiempo de ejecución preferido y la compatibilidad con la interfaz IPreferredRuntimeTypeConcept.
La interfaz IPreferredRuntimeTypeConcept se declara de la siguiente manera:
DECLARE_INTERFACE_(IPreferredRuntimeTypeConcept, IUnknown)
{
STDMETHOD(CastToPreferredRuntimeType)(_In_ IModelObject* contextObject, _COM_Errorptr_ IModelObject** object) PURE;
}
Se llama al método CastToPreferredRuntimeType cada vez que un cliente desea intentar convertir de una instancia de tipo estático al tipo en tiempo de ejecución de esa instancia. Si el objeto en cuestión admite (a través de uno de sus modelos primarios adjuntos), se llamará a este método para realizar la conversión. Este método puede devolver el objeto original (no hay ninguna conversión o no se pudo analizar), devolver una nueva instancia del tipo en tiempo de ejecución, producir un error por motivos no semánticos (por ejemplo: memoria insuficiente) o devolver E_NOT_SET. El código de error E_NOT_SET es un código de error muy especial que indica al modelo de datos que la implementación no desea invalidar el comportamiento predeterminado y que el modelo de datos debe revertir al análisis que realice el host de depuración (por ejemplo: análisis RTTI, examen de la forma de las tablas de funciones virtuales, etc.
Conceptos del proveedor dinámico: IDynamicKeyProviderConcept e IDynamicConceptProviderConcept
Aunque el propio modelo de datos normalmente controla la administración de claves y conceptos para los objetos, hay ocasiones en las que esa noción es menor que la ideal. En concreto, cuando un cliente desea crear un puente entre el modelo de datos y otra cosa que sea verdaderamente dinámica (por ejemplo, JavaScript), puede ser útil asumir la administración de claves y conceptos de la implementación en el modelo de datos. Como el modelo de datos principal es la única implementación de IModelObject, esto se hace en su lugar a través de una combinación de dos conceptos: el concepto de proveedor de claves dinámicas y el concepto de proveedor de conceptos dinámicos. Aunque sería habitual implementar ambos o ninguno de ellos, no hay ningún requisito para ello.
Si se implementan ambos, se debe agregar el concepto de proveedor de claves dinámicas antes del concepto de proveedor de concepto dinámico. Ambos conceptos son especiales. Invierten eficazmente un modificador en el objeto que lo cambia de "administrado estáticamente" a "administrado dinámicamente". Estos conceptos solo se pueden establecer si no hay claves o conceptos administrados por el modelo de datos en el objeto. Una vez agregados estos conceptos a un objeto, la acción de hacerlo es irreversible.
Hay una diferencia semántica adicional en torno a la extensibilidad entre un IModelObject, que es un proveedor de concepto dinámico y otro que no lo es. Estos conceptos están diseñados para permitir que los clientes creen puentes entre el modelo de datos y los sistemas de lenguaje dinámico, como JavaScript. El modelo de datos tiene un concepto de extensibilidad que difiere algo fundamentalmente de sistemas como JavaScript en que hay un árbol de modelos primarios en lugar de una cadena lineal como la cadena de prototipos de JavaScript. Para permitir una mejor relación con estos sistemas, un IModelObject que es un proveedor de concepto dinámico tiene un único modelo de datos primario. Ese modelo de datos único primario es un IModelObject normal que puede tener un número arbitrario de modelos primarios, como es habitual para el modelo de datos. Las solicitudes al proveedor de concepto dinámico para agregar o quitar elementos primarios se redirigen automáticamente al elemento primario único. Desde la perspectiva de un exterior, parece que el proveedor de concepto dinámico tiene una cadena de estilo de árbol normal de los modelos primarios. El implementador del concepto de proveedor de concepto dinámico es el único objeto (fuera del modelo de datos principal) que es consciente del elemento primario único intermedio. Ese elemento primario único se puede vincular con el sistema de lenguaje dinámico para proporcionar un puente (por ejemplo, colocado en la cadena de prototipos de JavaScript).
El concepto de proveedor de claves dinámicas se define de la siguiente manera:
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;
}
El concepto de proveedor de conceptos dinámicos se define de la siguiente manera:
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 de IDynamicKeyProviderConcept
El método GetKey en un proveedor de claves dinámicas es en gran medida una invalidación del método GetKey en IModelObject. Se espera que el proveedor de claves dinámicas devuelva el valor de la clave y los metadatos asociados a esa clave. En caso de que la clave no esté presente (pero no se produce ningún otro error), el proveedor debe devolver false en el parámetro hasKey y tener éxito con S_OK. Si se produce un error en esta llamada, se considera un error al capturar una clave y se detiene explícitamente la búsqueda de la clave a través de la cadena de modelos primaria. La devolución de false en hasKey y correcto continuará la búsqueda de la clave. Tenga en cuenta que es perfectamente legal que GetKey devuelva un descriptor de acceso de propiedad boxed como clave. Esto sería semánticamente idéntico al método GetKey en IModelObject que devuelve un descriptor de acceso de propiedad.
IDynamicKeyProviderConcept's SetKey
El método SetKey en un proveedor de claves dinámicas es eficazmente una invalidación del método SetKey en IModelObject. Esto establece una clave en el proveedor dinámico. Es efectivamente la creación de una nueva propiedad en el proveedor. Tenga en cuenta que un proveedor que no admite ninguna noción de algo como la creación de propiedades expando debe devolver E_NOTIMPL aquí.
EnumerateKeys del IDynamicKeyProviderConcept
El método EnumerateKeys en un proveedor de claves dinámicas es efectivamente una invalidación del método EnumerateKeys en IModelObject. Esto enumera todas las claves del proveedor dinámico. El enumerador devuelto tiene varias restricciones que la implementación debe respetar:
- Debe comportarse como una llamada a EnumerateKeys y no EnumerateKeyValues o EnumerateKeyReferences. Debe devolver los valores de clave que no resuelvan ningún descriptor de acceso de propiedad subyacente (si este concepto existe en el proveedor).
- Desde la perspectiva de un único proveedor de claves dinámicas, no es válido enumerar varias claves del mismo nombre que son claves físicamente distintas. Esto puede ocurrir en distintos proveedores que se adjuntan a través de la cadena de modelos primarios, pero no puede ocurrir desde la perspectiva de un único proveedor.
GetConcept de IDynamicConceptProviderConcept
El método GetConcept en un proveedor de concepto dinámico es efectivamente una invalidación del método GetConcept en IModelObject. El proveedor de concepto dinámico debe devolver una interfaz para el concepto consultado si existe, así como los metadatos asociados a ese concepto. Si el concepto no existe en el proveedor, debe indicarse a través de un valor false que se devuelve en el argumento hasConcept y una devolución correcta. El error de este método es un error al capturar el concepto y detendrá explícitamente la búsqueda del concepto. Devolver false para hasConcept y un código correcto continuará la búsqueda del concepto a través del árbol del modelo primario.
SetConcept de IDynamicConceptProviderConcept
El método SetConcept en un proveedor de concepto dinámico es efectivamente una invalidación del método SetConcept en IModelObject. El proveedor dinámico asignará el concepto. Esto puede hacer que el objeto sea iterable, indizable, cadena convertible, etc... Tenga en cuenta que un proveedor que no permite la creación de conceptos en él debe devolver E_NOPTIMPL aquí.
NotifyParent de IDynamicConceptProviderConcept
El modelo de datos principal usa la llamada NotifyParent en un proveedor de concepto dinámico para informar al proveedor dinámico del modelo primario único que se crea para permitir el puente del paradigma de "varios modelos primarios" del modelo de datos a lenguajes más dinámicos. Cualquier manipulación de ese modelo primario único provocará más notificaciones al proveedor dinámico. Tenga en cuenta que esta devolución de llamada se realiza inmediatamente tras la asignación del concepto de proveedor de concepto dinámico.
NotifyParentChange de IDynamicConceptProviderConcept
El método NotifyParent en un proveedor de concepto dinámico es una devolución de llamada realizada por el modelo de datos principal cuando se realiza una manipulación estática del modelo primario único del objeto. Para cualquier modelo primario determinado agregado, este método se llamará una primera vez cuando se agregue dicho modelo primario y una segunda vez si se quita dicho modelo primario o cuando se quita dicho modelo primario.
NotifyDestruct de IDynamicConceptProviderConcept
El método NotifyDestruct en un proveedor de concepto dinámico es una devolución de llamada realizada por el modelo de datos principal al principio de la destrucción del objeto, que es un proveedor de concepto dinámico. Proporciona oportunidades de limpieza adicionales a los clientes que lo requieren.
--
Consulte también
Este tema forma parte de una serie que describe las interfaces accesibles desde C++, cómo usarlas para compilar una extensión de depurador basada en C++ y cómo usar otras construcciones de modelo de datos (por ejemplo: JavaScript o NatVis) desde una extensión de modelo de datos de C++.
Información general sobre el modelo de datos del depurador de C++
Interfaces del modelo de datos de depurador C++
Objetos de C++ del modelo de datos del depurador
Interfaces adicionales del modelo de datos del depurador de C++