Megosztás a következőn keresztül:


Metaadatok és önleíró összetevők

Korábban az egyik nyelven írt szoftverösszetevő (.exe vagy .dll) nem tudta könnyen használni egy másik nyelven írt szoftverösszetevőt. A COM egy lépést tett a probléma megoldása felé. A .NET még egyszerűbbé teszi az összetevők együttműködését azáltal, hogy lehetővé teszi a fordítók számára, hogy további deklaratív információkat bocsáthassanak ki az összes modulba és szerelvényekbe. Ezek az úgynevezett metaadatok segítenek az összetevőknek a zökkenőmentes interakcióban.

A metaadatok olyan bináris információk, amelyek a programot leíró bináris információk, amelyeket egy közös nyelvi futtatókörnyezeti hordozható végrehajtható fájlban (PE) vagy a memóriában tárolnak. Amikor egy PE-fájlba fordítja a kódot, a rendszer metaadatokat szúr be a fájl egyik részébe, a kód pedig köznapi köztes nyelvre (CIL) lesz konvertálva, és a fájl egy másik részébe lesz beszúrva. A modulban vagy szerelvényben definiált és hivatkozott összes típust és tagot a metaadatok ismertetik. A kód végrehajtásakor a futtatókörnyezet betölti a metaadatokat a memóriába, és arra hivatkozik, hogy információkat derítsen fel a kód osztályairól, tagjairól, örökléséről stb.

A metaadatok a kódban definiált összes típust és tagot nyelvsemleges módon írják le. A metaadatok a következő információkat tárolják:

  • A szerelvény leírása.

    • Identitás (név, verzió, kultúra, nyilvános kulcs).

    • Az exportált típusok.

    • Egyéb szerelvények, amelyektől ez a szerelvény függ.

    • A futtatáshoz szükséges biztonsági engedélyek.

  • A típusok leírása.

    • Név, láthatóság, alaposztály és implementált felületek.

    • Tagok (metódusok, mezők, tulajdonságok, események, beágyazott típusok).

  • Attribútumok.

    • További leíró elemek, amelyek módosítják a típusokat és a tagokat.

A metaadatok előnyei

A metaadatok az egyszerűbb programozási modell kulcsai, és szükségtelenné teszi az interfészdefiníciós nyelv (IDL) fájljait, fejlécfájljait vagy bármely külső összetevő-referenciametódus használatát. A metaadatok lehetővé teszik, hogy a .NET-nyelvek automatikusan, nyelvsemleges módon írjanak le magukról, a fejlesztő és a felhasználó által nem látott módon. Emellett a metaadatok attribútumok használatával bővíthetők. A metaadatok a következő főbb előnyöket biztosítják:

  • Önleíró fájlok.

    A gyakori nyelvi futtatókörnyezeti modulok és szerelvények önleírók. A modul metaadatai mindent tartalmaznak, ami egy másik modullal való interakcióhoz szükséges. A metaadatok automatikusan biztosítják az IDL funkcióit a COM-ban, így egy fájlt használhat a definícióhoz és a megvalósításhoz is. A futtatókörnyezeti modulok és szerelvények nem is igényelnek regisztrációt az operációs rendszerrel. Ennek eredményeképpen a futtatókörnyezet által használt leírások mindig a lefordított fájl tényleges kódját tükrözik, ami növeli az alkalmazás megbízhatóságát.

  • Nyelvi együttműködés és egyszerűbb összetevőalapú kialakítás.

    A metaadatok a lefordított kódhoz szükséges összes információt biztosítják ahhoz, hogy egy osztályt egy másik nyelven írt PE-fájlból örököljön. Bármely osztály egy példányát bármilyen felügyelt nyelven (bármely olyan nyelven, amely a közös nyelvi futtatókörnyezetet célozza) anélkül hozhat létre példányt, hogy explicit rendezéssel vagy egyéni együttműködési kóddal kellene foglalkoznia.

  • Attribútumok.

    A .NET lehetővé teszi bizonyos metaadatok, úgynevezett attribútumok deklarálását a lefordított fájlban. Az attribútumok a .NET-ben találhatók, és részletesebben szabályozhatók, hogyan viselkedik a program futásidőben. Emellett saját egyéni metaadatokat is kibocsáthat .NET-fájlokba felhasználó által definiált egyéni attribútumok használatával. További információ: Attribútumok.

Metaadatok és a PE-fájlstruktúra

A metaadatokat egy .NET hordozható végrehajtható fájl (PE) egyik szakaszában tárolja a rendszer, míg a közös köztes nyelvet (CIL) a PE-fájl egy másik szakaszában tárolja a rendszer. A fájl metaadat-része táblázat- és halom adatstruktúrák sorozatát tartalmazza. A CIL rész olyan CIL- és metaadat-jogkivonatokat tartalmaz, amelyek a PE-fájl metaadat-részére hivatkoznak. Metaadat-jogkivonatokkal találkozhat, ha például az IL-szétszerelt eszközt (Ildasm.exe) használja a kód CIL-jének megtekintéséhez.

Metaadattáblák és halom

Minden metaadattábla információkat tartalmaz a program elemeiről. Az egyik metaadattábla például a kód osztályait írja le, egy másik tábla pedig a mezőket stb. Ha a kódban tíz osztály szerepel, az osztálytábla több tíz sorból áll, egy-egy osztályhoz. A metaadattáblák más táblákra és halmokra hivatkoznak. Az osztályok metaadattáblája például a metódusok táblára hivatkozik.

A metaadatok emellett négy halomstruktúrában tárolják az információkat: sztring, blob, felhasználói sztring és GUID. A névtípusokhoz és tagokhoz használt összes sztring a sztring halomba kerül. A metódustáblák például nem tárolják közvetlenül egy adott metódus nevét, hanem a metódusnak a sztringben tárolt nevére mutatnak.

Metaadat-jogkivonatok

Az egyes metaadattáblák minden sora egyedileg van azonosítva a PE-fájl CIL-részében egy metaadat-jogkivonattal. A metaadat-jogkivonatok fogalmilag hasonlítanak a CIL-ben megmaradó, egy adott metaadattáblára hivatkozó mutatókhoz.

A metaadat-jogkivonat egy négy bájtos szám. A felső bájt azt a metaadattáblát jelöli, amelyre egy adott jogkivonat hivatkozik (metódus, típus stb.). A fennmaradó három bájt adja meg a metaadat-tábla azon sorát, amely megfelel a leírt programozási elemnek. Ha a C#-ban definiál egy metódust, és pe-fájlba fordítja, a következő metaadat-jogkivonat létezhet a PE-fájl CIL-részében:

0x06000004

A felső bájt (0x06) azt jelzi, hogy ez egy MethodDef-jogkivonat . Az alsó három bájt (000004) arra utasítja a közös nyelvi futtatókörnyezetet, hogy a MethodDef tábla negyedik sorában keresse meg a metódusdefiníciót leíró információkat.

Metaadatok pe-fájlon belül

Amikor egy programot lefordítanak a közös nyelvi futtatókörnyezethez, a program egy három részből álló PE-fájllá alakítja. Az alábbi táblázat az egyes részeket ismerteti.

PE szakasz A PE szakasz tartalma
PE fejléc A PE-fájl fő szakaszainak indexe és a belépési pont címe.

A futtatókörnyezet ezen információk alapján azonosítja a fájlt PE-fájlként, és meghatározza, hogy hol kezdődik a végrehajtás a program memóriába való betöltésekor.
CIL-utasítások A Microsoft köztes nyelvi utasításai (CIL), amelyek a kódot alkotják. A CIL számos utasítását metaadat-jogkivonatok kísérik.
Metaadatok Metaadattáblák és halom. A futtatókörnyezet ebben a szakaszban rögzíti a kód minden típusával és tagával kapcsolatos információkat. Ez a szakasz egyéni attribútumokat és biztonsági információkat is tartalmaz.

Metaadatok futásidejű használata

A metaadatok és a közös nyelvi futtatókörnyezetben betöltött szerepének jobb megértése érdekében hasznos lehet egy egyszerű program létrehozása és a metaadatok futásidejének befolyásolása. Az alábbi példakód két metódust mutat be egy úgynevezett MyApposztályon belül. A Main metódus a program belépési pontja, míg a Add metódus egyszerűen két egész argumentum összegét adja vissza.

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);
   }
}

A kód futtatásakor a futtatókörnyezet betölti a modult a memóriába, és áttekinti az osztály metaadatait. A betöltés után a futtatókörnyezet átfogó elemzést végez a metódus közös köztes nyelvű (CIL) streamjéről, hogy gyors natív gépi utasításokká alakítsa azt. A futtatókörnyezet egy igény szerinti (JIT) fordítóval konvertálja a CIL-utasításokat natív gépkóddá, szükség szerint egy módszerrel.

Az alábbi példa az előző kód Main függvényéből előállított CIL egy részét mutatja be. A CIL-t és a metaadatokat bármely .NET-alkalmazásból megtekintheti a CIL-szétszerelési eszközzel (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 */

A JIT-fordító beolvassa a teljes metódushoz tartozó CIL-t, alaposan elemzi, és hatékony natív utasításokat hoz létre a metódushoz. Ekkor IL_000dmegjelenik a Add metódus (/*06000003 */) metaadat-jogkivonata, és a futtatókörnyezet a tokent használja a MethodDef tábla harmadik sorának megtekintéséhez.

Az alábbi táblázat a metódust leíró Add metaadat-jogkivonat által hivatkozott MethodDef tábla egy részét mutatja be. Bár más metaadattáblák is léteznek ebben a szerelvényben, és saját egyedi értékekkel rendelkeznek, csak ezt a táblát tárgyaljuk.

Sor Relatív virtuális cím (RVA) ImplFlags Zászlók Név

(A sztring halomra mutat.)
Aláírás (A blob halomra mutat.)
0 0x00002050 IL

Felügyelt
Nyilvános

ReuseSlot

Speciális név

RTSpecialName

.ctor
.ctor (konstruktor)
2 0x00002058 IL

Felügyelt
Nyilvános

Statikus

ReuseSlot
Elsődleges Sztring
3 0x0000208c IL

Felügyelt
Nyilvános

Statikus

ReuseSlot
Hozzáadás int, int, int

A tábla minden oszlopa fontos információkat tartalmaz a kódról. Az RVA oszlop lehetővé teszi, hogy a futtatókörnyezet kiszámítsa a metódust meghatározó CIL kezdő memóriacímét. Az ImplFlags és a Flags oszlop bitmaszkokat tartalmaz, amelyek a metódust írják le (például hogy a metódus nyilvános vagy privát). A Név oszlop indexeli a metódus nevét a sztring halomból. Az Aláírás oszlop indexeli a metódus aláírásának definícióját a blob halomban.

A futtatókörnyezet kiszámítja a kívánt eltolási címet a harmadik sorban lévő RVA oszlopból, és visszaadja ezt a címet a JIT-fordítónak, amely ezután az új címre tér vissza. A JIT-fordító addig dolgozza fel a CIL-t az új címen, amíg egy másik metaadat-jogkivonattal nem találkozik, és a folyamat meg nem ismétlődik.

A metaadatok használatával a futtatókörnyezet hozzáfér a kód betöltéséhez és natív gépi utasításokba való feldolgozásához szükséges összes információhoz. Ily módon a metaadatok lehetővé teszik az önleíró fájlokat, és a gyakori típusrendszerrel együtt a nyelvközi öröklést.