Používání metadat v době běhu
Pro lepší pochopení metadat a jejich úlohy v modulu CLR (Common Language Runtime) může být užitečné vytvořit jednoduchý program a ukázat tak, jak metadata ovlivňují jeho život za běhu. Následující příklad kódu ukazuje dvě metody uvnitř třídy nazvané MyApp. Metoda Main je vstupní bod programu, zatímco metoda Add jednoduše vrací součet dvou celočíselných argumentů.
Public Class MyApp
Public Shared Sub Main()
Dim ValueOne As Integer = 10
Dim ValueTwo As Integer = 20
Console.WriteLine("The Value is: {0}", Add(ValueOne, ValueTwo))
End Sub
Public Shared Function Add(One As Integer, Two As Integer) As Integer
Return (One + Two)
End Function
End Class
using System;
public class MyApp
{
public static int Main()
{
int ValueOne = 10;
int ValueTwo = 20;
Console.WriteLine("The Value is: {0}", Add(ValueOne, ValueTwo));
return 0;
}
public static int Add(int One, int Two)
{
return (One + Two);
}
}
Když se kód spustí, tak runtime modul zavádí modul do paměti a bere v úvahu metadata pro tuto třídu. Po načtení runtime modul provádí rozsáhlou analýzu datového proudu jazyka MSIL(Microsoft intermediate language), který náleží metodám za účelem jeho rychlého převedení do nativních instrukcí počítače. Modul runtime k převedení MSIL instrukcí do nativního strojového kódu používá just-in-time (JIT) kompilátor. Převedena může být současně jedna metoda.
Následující příklad ukazuje části jazyka MSIL vytvořené z předchozího kódu funkce Main. Jazyk MSIL a metadata lze vidět z libovolné aplikace rozhraní .NET Framework pomocí MSIL Disassembler (Ildasm.exe).
.entrypoint
.maxstack 3
.locals ([0] int32 ValueOne,
[1] int32 ValueTwo,
[2] int32 V_2,
[3] int32 V_3)
IL_0000: ldc.i4.s 10
IL_0002: stloc.0
IL_0003: ldc.i4.s 20
IL_0005: stloc.1
IL_0006: ldstr "The Value is: {0}"
IL_000b: ldloc.0
IL_000c: ldloc.1
IL_000d: call int32 ConsoleApplication.MyApp::Add(int32,int32) /* 06000003 */
JIT kompilátor čte MSIL pro celou metodu, důkladně ji analyzuje a generuje pro ni efektivní nativní instrukce. V IL_000d je naraženo na příznak metadat pro metodu Add (/* 06000003 */), modul runtime příznak používá ke konzultaci třetího řádku tabulky MethodDef.
Následující tabulka ukazuje části tabulky MethodDef, ta je odkazována příznakem metadat, který popisuje metodu Add. I když v tomto sestavení existují jiné tabulky metadat, které mají své vlastní jedinečné hodnoty, tak pouze tato tabulka je diskutována.
Řádek |
Relativní virtuální adresa (RVA) |
ImplFlags |
Příznaky |
Název (Ukazuje na haldu řetězce.) |
Signatura (Ukazuje na haldu binárního rozsáhlého objektu.) |
---|---|---|---|---|---|
1 |
0x00002050 |
IL Spravované |
Veřejné ReuseSlot SpecialName RTSpecialName .ctor |
.ctor (konstruktor) |
|
2 |
0x00002058 |
IL Spravované |
Veřejné Statické ReuseSlot |
Hlavní |
Řetězec |
3 |
0x0000208c |
IL Spravované |
Veřejné Statické ReuseSlot |
Přidejte |
int, int, int |
Každý sloupec tabulky obsahuje důležité informace o kódu. Sloupec RVA umožňuje modulu runtime vypočítat počáteční adresu paměti MSIL kódu, který definuje tuto metodu. Sloupce ImplFlags a Příznaky obsahují bitovou masku popisující metodu (například zda metoda je veřejná nebo privátní). Sloupec Název indexuje název metody z haldy řetězce. Sloupec Signatura indexuje definici signatury metody v haldě binárního rozsáhlého objektu.
Modul runtime vypočítá požadovanou adresu posunu ze sloupce RVA v třetím řádku a vrátí tuto adresu JIT kompilátoru, který pak pokračuje na novou adresu. JIT kompilátor pokračuje ve zpracování MSIL na nové adrese, dokud nenarazí na jiný příznak metadat a proces se opakuje.
Díky používání metadat má runtime modul přístup k veškerým informacím, které potřebuje k načtení kódu a jeho zpracování do nativních strojových instrukcí. Tímto způsobem metadata umožňují samo-popisující soubory a společně se specifikací CTS (Common Type System) mezi jazykovou dědičnost.