Los metadatos , en la Infraestructura de lenguaje común (CLI), hacen referencia a ciertas estructuras de datos integradas en el código del Lenguaje intermedio común (CIL) que describen la estructura de alto nivel del código. Los metadatos describen todas las clases y los miembros de clase que se definen en el ensamblado, y las clases y los miembros de clase que el ensamblado actual llamará desde otro ensamblado. Los metadatos de un método contienen la descripción completa del método, incluida la clase (y el ensamblado que contiene la clase), el tipo de retorno y todos los parámetros del método .
Un compilador de lenguaje CLI generará los metadatos y los almacenará en el ensamblado que contiene el CIL . Cuando el entorno de ejecución ejecuta el CIL, comprobará que los metadatos del método llamado sean los mismos que los metadatos almacenados en el método que realiza la llamada. Esto garantiza que un método solo se pueda llamar con exactamente la cantidad correcta de parámetros y exactamente los tipos de parámetros correctos.
La plataforma de aplicaciones Windows Runtime , presente en Windows 8 y Windows Phone 8 , utiliza el formato de metadatos CLI para describir las interfaces de componentes para el código escrito en cualquiera de los lenguajes de programación compatibles . Una diferencia en el uso dentro de Common Language Runtime es que un ensamblaje normalmente no contiene ninguna instrucción CIL. [1]
Los desarrolladores pueden agregar metadatos a su código a través de atributos . Hay dos tipos de atributos, personalizados y pseudopersonalizados, y para el desarrollador tienen la misma sintaxis . Los atributos en el código son mensajes que se envían al compilador para generar metadatos. En CIL, los metadatos, como los modificadores de herencia, los modificadores de alcance y casi cualquier cosa que no sean códigos de operación o secuencias, también se conocen como atributos.
Un atributo personalizado es una clase regular que hereda de la Attribute
clase. Un atributo personalizado se puede utilizar en cualquier método, propiedad, clase o conjunto completo con la sintaxis: como en:[AttributeName(optional parameter, optional name=value pairs)]
[Personalizado] [Personalizado(1)] [Personalizado(1, Comentario="sí")]
Los atributos personalizados son utilizados ampliamente por CLI. Windows Communication Framework utiliza atributos para definir contratos de servicio, ASP.NET los utiliza para exponer métodos como servicios web , LINQ to SQL los utiliza para definir la asignación de clases al esquema relacional subyacente , Visual Studio los utiliza para agrupar propiedades de un objeto, el desarrollador de la clase indica la categoría de la clase del objeto aplicando el [Category]
atributo personalizado. Los atributos personalizados son interpretados por el código de la aplicación y no por el CLR. Cuando el compilador ve un atributo personalizado, generará metadatos personalizados que el CLR no reconoce. El desarrollador tiene que proporcionar código para leer los metadatos y actuar en consecuencia. A modo de ejemplo, el atributo que se muestra en el ejemplo puede ser manejado por el código:
clase CustomAttribute : Atributo { int privado paramNumber = 0 ; cadena privada comentario = "" ; public CustomAttribute () { } public CustomAttribute ( int num ) { paramNumber = num ; } público String Comentario { conjunto { comentario = valor ; } } }
El nombre de la clase se asigna al nombre del atributo. El compilador de Visual C# agrega automáticamente la cadena " Attribute
" al final de cualquier nombre de atributo. En consecuencia, cada nombre de clase de atributo debe terminar con esta cadena, pero es legal definir un atributo sin el Attribute
sufijo -. Al agregar un atributo a un elemento, el compilador buscará tanto el nombre literal como el nombre con Attribute
agregado al final, es decir, si escribiera, [Custom]
el compilador buscaría tanto Custom
y CustomAttribute
. Si ambos existen, el compilador falla. El atributo puede tener como prefijo " @
" si no desea correr el riesgo de ambigüedad, por lo que la escritura [@Custom]
no coincidirá con CustomAttribute
. El uso del atributo invoca el constructor de la clase. Se admiten constructores sobrecargados. Los pares Nombre-Valor se asignan a propiedades, el nombre denota el nombre de la propiedad y el valor proporcionado lo establece la propiedad.
A veces existe ambigüedad en cuanto a qué se le está agregando al atributo. Considere el siguiente código:
[Naranja] public int ExampleMethod ( string input ) { //el cuerpo del método va aquí }
¿Qué se ha marcado como naranja? ¿Es el ExampleMethod
, su valor de retorno o quizás todo el ensamblaje? En este caso, el compilador tomará el valor predeterminado y tratará el atributo como si estuviera adjunto al método. Si esto no es lo que se pretendía, o si el autor desea aclarar su código, se puede especificar un destino de atributo[return: Orange]
. Al escribir se marcará el valor de retorno como naranja, se [assembly: Orange]
marcará todo el ensamblaje. Los destinos válidos son assembly
, field
, event
, method
, module
, param
, y .property
return
type
Un atributo pseudo-personalizado se utiliza igual que los atributos personalizados normales, pero no tienen un controlador personalizado; en lugar de eso, el compilador tiene un conocimiento intrínseco de los atributos y maneja el código marcado con dichos atributos de manera diferente. Los atributos como Serializable
y se implementan como atributos pseudo-personalizados. ILAsmObsolete
nunca debe utilizar atributos pseudo-personalizados , ya que tienen la sintaxis adecuada para describir los metadatos. [ aclaración necesaria ]
Los ensamblajes contienen tablas de metadatos. Estas tablas se describen en la especificación CIL. Las tablas de metadatos tendrán cero o más entradas y la posición de una entrada determina su índice. Cuando el código CIL utiliza metadatos, lo hace a través de un token de metadatos. Este es un valor de 32 bits donde los 8 bits superiores identifican la tabla de metadatos apropiada y los 24 bits restantes dan el índice de los metadatos en la tabla. El SDK de Framework contiene un ejemplo llamado metainfo
que enumerará las tablas de metadatos en un ensamblaje; sin embargo, esta información rara vez es de utilidad para un desarrollador. Los metadatos en un ensamblaje se pueden ver utilizando la herramienta ILDASM proporcionada por el SDK de .NET Framework .
En el estándar CIL, los metadatos se definen en formato ILAsm (lenguaje ensamblador), un formato de representación en disco para almacenamiento y un formato que se integra en los ensamblajes del formato Portable Executable (PE, .exe o .dll). El formato PE se basa en el formato en disco.
Reflection es la API que se utiliza para leer metadatos de la CLI. La API de Reflection proporciona una vista lógica de los metadatos en lugar de la vista literal que ofrecen herramientas como metainfo. Reflection en la versión 1.1 del marco .NET se puede utilizar para inspeccionar las descripciones de las clases y sus miembros, e invocar métodos. Sin embargo, no permite el acceso en tiempo de ejecución a la CIL de un método. La versión 2.0 del marco permite obtener la CIL de un método.
Además del System.Reflection
espacio de nombres, también hay otras herramientas disponibles que se pueden utilizar para manejar metadatos. Microsoft .NET Framework incluye una biblioteca de manipulación de metadatos CLR que se implementa en código nativo . También se pueden utilizar herramientas de terceros para recuperar y manipular metadatos, como PostSharp y Mono Cecil.