Tokens de metadatos
Los metadatos hacen referencia a información declarativa acerca de abstracciones tales como tipos en tiempo de ejecución (clases, tipos de valor e interfaces), funciones globales y variables globales. Los metadatos se almacenan en tablas de la siguiente manera: una tabla para cada categoría de abstracción y una fila de la tabla para cada declaración de una abstracción. Para localizar el registro que contiene los metadatos de una abstracción se utiliza un símbolo (token), que es un objeto de tipo mdToken. El motor de metadatos utiliza el símbolo (token) para indizar una tabla de metadatos específica en un ámbito de metadatos dado.
Estructura de los símbolos (tokens) de metadatos
Un símbolo (token) de metadatos es un valor de 4 bytes. El byte más significativo (MSB) especifica el tipo de token y, por consiguiente, identifica la abstracción y la tabla de metadatos asociada. Por ejemplo, un valor de 1 en el MSB indica que el token es un token mdTypeRef, que representa una referencia de tipo, y que sus metadatos se almacenan en la tabla de metadatos TypeRef; un valor de 4 en el MSB corresponde a un token mdFieldDef. La enumeración CorTokenType se utiliza para especificar los tipos de token.
Los tres bytes más bajos, que reciben el nombre de identificador del registro (RID), contienen el índice de la fila de la tabla de metadatos a la que hace referencia el MSB del token. Por ejemplo, el símbolo (token) de metadatos con el valor 0x02000007 hace referencia a la fila 7 de la tabla TypeDef en el ámbito actual. De igual forma, el símbolo (token) 0x0400001A hace referencia a la fila 26 (decimal) de la tabla FieldDef en el ámbito actual. La fila cero de una tabla de metadatos nunca contiene datos, por lo que un símbolo (token) de metadatos cuyo RID es cero se conoce como símbolo (token) nil. La API de metadatos define varios símbolos (token) nil de esta clase, uno para cada tipo de símbolo (token), como mdTypeRefNil, con el valor 0x01000000.
Nota |
---|
La explicación anterior acerca de los RID es conceptual; en realidad, el diseño físico de los metadatos es mucho más complejo.Además, los tokens de cadena (mdString) son ligeramente diferentes: los 3 bytes más bajos no son un identificador de registro, sino un desplazamiento respecto a la posición inicial de la cadena en el grupo de cadenas de metadatos. |
Utilizar símbolos (tokens) de metadatos
Cada método DefineXXX de la API de metadatos devuelve un símbolo (token) que se puede pasar a un método GetXXX para obtener sus atributos asociados.
Los símbolos (tokens) de metadatos se definen dentro de un ámbito. Por ejemplo, un token de metadatos con el valor N identifica completamente, dentro de un ámbito determinado, un registro que contiene los detalles de una definición de tipo. Sin embargo, en un ámbito diferente, un token de metadatos con ese mismo valor N puede especificar un registro totalmente diferente.
Un token de metadatos no es un identificador inmutable de objetos de metadatos. Cuando se combinan dos ámbitos, los tokens del ámbito importado se reasignan a los tokens del ámbito emitido. Cuando se guarda un ámbito de metadatos, las diversas optimizaciones de formato pueden producir la reasignación de los símbolos (tokens).
Tipos de símbolos (tokens)
La tabla siguiente muestra los tipos de símbolos (tokens) de metadatos, la abstracción que representa cada tipo de símbolo (token) y el nombre de la tabla de metadatos que contiene los metadatos de la abstracción. Todos los tipos de símbolos (tokens) son variaciones de mdToken, que es el tipo de símbolo (token) básico.
Tipo de símbolo (token) |
Tabla de metadatos |
Abstracción |
---|---|---|
mdModule |
Módulo |
Módulo: unidad de compilación, aplicación ejecutable, o alguna otra unidad de desarrollo, unidad de implementación o unidad en tiempo de ejecución. Es posible (aunque no necesario) declarar en conjunto los atributos en el módulo, incluidos el nombre, GUID, atributos personalizados, etc. |
mdModuleRef |
ModuleRef |
Referencia de módulo: referencia a un módulo en tiempo de compilación, que registra el origen de las importaciones de tipos y miembros. |
mdTypeDef |
TypeDef |
Tipo de declaración: declaración de un tipo de referencia en tiempo de ejecución (clase o interfaz) o de un tipo de valor. |
mdTypeRef |
TypeRef |
Referencia de tipo: referencia a un tipo de referencia en tiempo de ejecución o a un tipo de valor. En cierto sentido, la colección de referencias de tipo en un módulo es la colección de dependencias de importación en tiempo de compilación. |
mdMethodDef |
MethodDef |
Definición de método: definición de un método como miembro de una clase o interfaz, o como método global de nivel de módulo. |
mdParamDef |
ParamDef |
Declaración de parámetro: definición de una estructura de datos opcional que almacena metadatos adicionales para el parámetro. No es necesario emitir una estructura de datos para cada parámetro de un método. Sin embargo, cuando se deben conservar metadatos adicionales para el parámetro, como información de cálculo de referencias o de asignación de tipos, se puede crear una estructura de datos de parámetro opcional. |
mdFieldDef |
FieldDef |
Declaración de campo: declaración de una variable como miembro de datos de una clase o interfaz, o declaración de una variable global en el nivel de módulo. |
mdProperty |
Propiedad |
Declaración de propiedad: declaración de una propiedad como miembro de una clase o interfaz. |
mdEvent |
Evento |
Declaración de evento: declaración de un evento con nombre como miembro de una clase o interfaz. |
mdMemberRef |
MemberRef |
Referencia de miembro: referencia a un método o campo. En los metadatos se genera una referencia de miembro para cada invocación de método o acceso de campo efectuado por cualquier implementación en el módulo actual, y se conserva un token en la secuencia de lenguaje intermedio de Microsoft (MSIL). No existe compatibilidad en tiempo de ejecución para referencias de propiedad o de evento. |
mdIfaceImpl |
IfaceImpl |
Implementación de interfaz: implementación de una interfaz específica de una clase concreta. Esta abstracción de metadatos permite almacenar información que representa la intersección de algo que no es específico ni de la clase ni de la interfaz. |
mdMethodImpl |
MethodImpl |
Implementación de método: implementación de un método de una clase concreta heredado mediante la herencia de interfaces. Esta abstracción de los metadatos permite conservar información que es específica de la implementación y no del contrato. La clase de implementación no puede modificar la información de declaración del método. |
mdCustomAttribute |
CustomAttribute |
Atributo personalizado: estructura de datos arbitraria asociada a cualquier objeto de metadatos al que se puede hacer referencia con mdToken. (Una excepción es que los propios atributos personalizados no pueden tener atributos personalizados.) |
mdPermission |
Permiso |
Conjunto de permisos: conjunto de permisos de seguridad declarativa asociado a mdTypeDef, mdMethodDef y mdAssembly. Para obtener más información, vea Agregar compatibilidad con la seguridad declarativa. |
mdTypeSpec |
TypeSpec |
Constructor de tipos: método que obtiene un token para un tipo (como un tipo de valor al que se le ha aplicado la conversión boxing) que se puede utilizar como entrada para cualquier instrucción de MSIL que utilice un tipo. |
mdSignature |
Firma |
Firma independiente: firma de variable local en el archivo portable ejecutable (PE) o firma de método que se pasa a una instrucción de MSIL. |
mdString |
String |
Cadena de usuario: cadena que se pasa a una instrucción de MSIL. |
Nota |
---|
La lista anterior no incluye dos tipos de símbolos (tokens) independientes, uno para una referencia de campo y otro para una referencia de método, como se podría esperar.Las referencias de campo y método comparten la misma tabla y se puede hacer referencia a ellos utilizando el tipo de token mdMemberRef. |
Extensibilidad y abstracciones
Los metadatos en tiempo de ejecución son extensibles, lo que es importante en los escenarios siguientes:
Para representar restricciones o abstracciones de nivel superior definidas en Common Language Specification (CLS). CLS es una especificación de las convenciones que cumplen los lenguajes y las herramientas de manera uniforme para una mejor integración del lenguaje. CLS puede limitar algunas partes del modelo del sistema de tipos común y puede introducir abstracciones de nivel superior que se superponen al sistema de tipos común. Los metadatos deben capturar estos tipos de abstracciones en tiempo de desarrollo que utilizan las herramientas, aunque el motor en tiempo de ejecución no las reconozca o no las admita de manera explícita.
Para representar abstracciones específicas del lenguaje que no forman parte del sistema de tipos común y no son abstracciones de CLS. Esto permite que lenguajes como Visual C no necesiten archivos IDL o archivos de encabezado independientes para utilizar los tipos, métodos y miembros de datos exportados por los módulos compilados.
Para codificar los tipos de firmas de miembro y los modificadores de tipos que se utilizan en la sobrecarga específica del lenguaje.
La extensibilidad de los metadatos consiste en lo siguiente:
Cada objeto de metadatos puede admitir atributos personalizados, y las API de metadatos proporcionan una manera de declarar, enumerar y recuperar los atributos personalizados. Los atributos personalizados se pueden identificar mediante una referencia de tipo (mdTypeDef y mdTypeRef). La estructura del atributo personalizado es autodescriptiva (utiliza miembros de datos declarados en el tipo) y la codificación de los valores se puede examinar con cualquier herramienta, incluidos los servicios de reflexión en tiempo de ejecución.
Además de extender el sistema de tipos común, es posible emitir modificadores personalizados en las firmas de miembro. El motor en tiempo de ejecución admitirá estos modificadores para la sobrecarga y la ocultación de métodos, así como para el enlace, pero no impondrá ninguna semántica específica del lenguaje.