En la plataforma .NET se
distinguen dos tipos de módulos de
código compilado: ejecutables
(extensión .exe) y librerías de enlace dinámico (extensión
.dll generalmente) Ambos son
ficheros que contienen definiciones de tipos de datos, y la diferencia entre
ellos es que sólo los primeros disponen de un método especial que sirve de
punto de entrada a partir del que es posible ejecutar el código que contienen
haciendo una llamada desde la línea de comandos del sistema operativo. A ambos
tipos de módulos se les suele llamar ejecutables
portables (PE), ya que su código puede ejecutarse en cualquiera de los
diferentes sistemas operativos de la familia Windows para los que existe alguna
versión del CLR.
El contenido de un módulo no sólo
MSIL, sino que también consta de otras dos áreas muy importantes: la cabecera
de CLR y los metadatos:
·
La cabecera de
CLR es un pequeño bloque de información que indica que se trata de un
módulo gestionado e indica es la versión del CLR que necesita, cuál es su firma
digital, cuál es su punto de entrada (si es un ejecutable), etc.
·
Los metadatos
son un conjunto de datos organizados en forma de tablas que almacenan
información sobre los tipos definidos en el módulo, los miembros de éstos y
sobre cuáles son los tipos externos al módulo a los que se les referencia en el
módulo. Los metadatos de cada modulo los genera automáticamente el compilador
al crearlo, y entre sus tablas se incluyen:
Tabla
|
Descripción
|
|
ModuleDef
|
Define las características del
módulo. Consta de un único elemento que almacena un identificador de versión
de módulo (GUID creado por el compilador) y el nombre de fichero que se dio
al módulo al compilarlo (así este nombre siempre estará disponible, aunque se
renombre el fichero)
|
|
TypeDef
|
Define las características de
los tipos definidos en el módulo. De cada tipo se almacena su nombre, su tipo
padre, sus modificadores de acceso y referencias a los elementos de las
tablas de miembros correspondientes a sus miembros.
|
|
MethodDef
|
Define las características de
los métodos definidos en el módulo. De cada método se guarda su nombre,
signatura (por cada parámetro se incluye una referencia al elemento apropiado
en la tabla ParamDef), modificadores y posición del módulo donde comienza el
código MSIL de su cuerpo.
|
|
ParamDef
|
Define las características de
los parámetros definidos en el módulo. De cada parámetro se guarda su nombre
y modificadores.
|
|
FieldDef
|
Define las características de
los campos definidos en el módulo. De cada uno se almacena información sobre
cuál es su nombre, tipo y modificadores.
|
|
PropertyDef
|
Define las características de
las propiedades definidas en el módulo. De cada una se indica su nombre,
tipo, modificadores y referencias a los elementos de la tabla MethodDef
correspondientes a sus métodos set/get.
|
|
EventDef
|
Define las características de
los eventos definidos en el módulo. De cada uno se indica su nombre, tipo,
modificadores. y referencias a los elementos de la tabla MethodDef
correspondientes a sus métodos add/remove.
|
|
AssemblyRef
|
Indica cuáles son los
ensamblados externos a los que se referencia en el módulo. De cada uno se
indica cuál es su nombre de fichero (sin extensión), versión, idioma y marca
de clave pública.
|
|
ModuleRef
|
Indica cuáles son los otros
módulos del mismo ensamblado a los que referencia el módulo. De cada uno se
indica cuál es su nombre de fichero.
|
|
TypeRef
|
Indica cuáles son los tipos
externos a los que se referencia en el módulo. De cada uno se indica cuál es su nombre y, según donde
estén definidos, una referencia a la posición adecuada en la tabla
AssemblyRef o en la tabla ModuleRef.
|
|
MemberRef
|
Indican cuáles son los miembros
definidos externamente a los que se referencia en el módulo. Estos miembros
pueden ser campos, métodos, propiedades o eventos; y de cada uno de ellos se
almacena información sobre su nombre y signatura, así como una referencia a
la posición de la tabla TypeRef donde se almacena información relativa al
tipo del que es miembro.
|
Tabla 1:
Principales tablas de metadatos
Nótese que el significado de los metadatos es similar al
de otras tecnologías previas a la plataforma .NET como lo son los ficheros IDL.
Sin embargo, los metadatos tienen dos ventajas importantes sobre éstas:
contiene más información y siempre se almacenan incrustados en el módulo al que
describen, haciendo imposible la separación entre ambos. Además, como se verá
más adelante, es posible tanto consultar los metadatos de cualquier módulo a
través de las clases del espacio de nombres System.Reflection de la BCL como añadirles información adicional
mediante atributos (se verá más adelante)