Bagikan melalui


Metadata dan Komponen yang Mendeskripsikan-Diri

Di masa lalu, komponen perangkat lunak (.exe atau .dll) yang ditulis dalam satu bahasa tidak dapat dengan mudah menggunakan komponen perangkat lunak yang ditulis dalam bahasa lain. COM menyediakan langkah ke arah pemecahan masalah ini. .NET membuat interoperaksi komponen lebih mudah dengan memungkinkan kompiler memancarkan informasi deklaratif tambahan ke semua modul dan rakitan. Informasi ini, yang disebut metadata, membantu komponen berinteraksi dengan mulus.

Metadata adalah informasi biner yang menjelaskan program Anda yang disimpan baik dalam file portable executable (PE) runtime bahasa umum atau dalam memori. Saat Anda mengkompilasi kode Anda ke dalam file PE, metadata dimasukkan ke dalam satu bagian file, dan kode Anda dikonversi ke bahasa perantara umum (CIL) dan dimasukkan ke bagian lain dari file. Setiap jenis dan anggota yang didefinisikan dan dirujuk dalam modul atau perakitan dijelaskan dalam metadata. Saat kode dijalankan, runtime memuat metadata ke dalam memori dan mereferensikannya untuk menemukan informasi tentang kelas, anggota, pewarisan kode, dan sebagainya.

Metadata menjelaskan setiap jenis dan anggota yang ditentukan dalam kode Anda dengan cara yang netral bahasa. Metadata menyimpan informasi berikut:

  • Deskripsi perakitan.

    • Identitas (nama, versi, budaya, kunci umum).

    • Jenis yang diekspor.

    • Rakitan lain yang tempat perakitan ini bergantung.

    • Izin keamanan diperlukan untuk menjalankan.

  • Deskripsi jenis.

    • Nama, visibilitas, kelas dasar, dan antarmuka yang diterapkan.

    • Anggota (metode, bidang, properti, peristiwa, jenis berlapis).

  • Atribut.

    • Elemen deskriptif tambahan yang memodifikasi jenis dan anggota.

Manfaat Metadata

Metadata adalah kunci untuk model pemrograman yang lebih sederhana, dan menghilangkan kebutuhan akan file Bahasa Definisi Antarmuka (IDL), file header, atau metode eksternal referensi apa pun dari referensi komponen. Metadata memungkinkan bahasa .NET untuk menggambarkan diri mereka secara otomatis dengan cara yang netral bahasa, yang tidak disadari oleh pengembang maupun pengguna. Selain itu, metadata dapat diperluas melalui penggunaan atribut. Metadata memberikan manfaat utama berikut:

  • File-yang mendeskripsikan diri.

    Modul dan rakitan runtime bahasa umum menjelaskan-sendiri. Metadata modul berisi semua yang diperlukan untuk berinteraksi dengan modul lain. Metadata secara otomatis menyediakan fungsionalitas IDL di COM, sehingga Anda dapat menggunakan satu file untuk definisi maupun implementasi. Modul dan rakitan runtime bahkan tidak perlu registrasi dengan sistem operasinya. Sebagai hasilnya, deskripsi yang digunakan oleh runtime selalu mencerminkan kode yang sebenarnnya dalam file yang dikompilasi, yang meningkatkan keandalan aplikasi.

  • Interoperabilitas bahasa dan desain berbasis komponen yang lebih mudah.

    Metadata menyediakan semua informasi yang diperlukan tentang kode yang dikompilasi bagi Anda untuk mewarisi kelas dari file PE yang ditulis dalam bahasa yang berbeda. Anda dapat membuat instans kelas apa pun yang ditulis dalam bahasa terkelola apa pun (bahasa apa pun yang menargetkan runtime bahasa umum) tanpa khawatir tentang pengerahan eksplisit atau menggunakan kode interoperabilitas kustom.

  • Atribut.

    .NET memungkinkan Anda mendeklarasikan jenis metadata tertentu, yang disebut atribut, dalam file yang dikompilasi. Atribut dapat ditemukan di seluruh .NET dan digunakan untuk mengontrol secara lebih rinci bagaimana program Anda berperilaku pada durasi. Selain itu, Anda dapat memancarkan metadata kustom Anda sendiri ke dalam file .NET melalui atribut kustom yang ditentukan-pengguna. Untuk informasi selengkapnya, lihat Atribut.

Metadata dan Struktur File PE

Metadata disimpan di satu bagian file .NET portable executable (PE), sementara bahasa perantara umum (CIL) disimpan di bagian lain dari file PE. Bagian metadata file berisi serangkaian struktur data tabel dan tumpukan. Bagian CIL berisi token CIL dan metadata yang mereferensikan bagian metadata file PE. Anda mungkin menemukan token metadata saat menggunakan alat seperti Il Disassembler (Ildasm.exe) untuk melihat CIL kode Anda, misalnya.

Tabel dan Tumpukan Metadata

Setiap tabel metadata menyimpan informasi tentang elemen program Anda. Misalnya, satu tabel metadata menjelaskan kelas dalam kode Anda, tabel lain menjelaskan bidang, dan sebagainya. Jika Anda memiliki sepuluh kelas dalam kode Anda, tabel kelas akan memiliki puluhan baris, satu baris untuk setiap kelas. Tabel metadata mereferensikan tabel dan tumpukan lainnya. Misalnya, tabel metadata untuk kelas mereferensikan tabel untuk metode.

Metadata juga menyimpan informasi dalam empat struktur tumpukan: string, blob, string pengguna, dan GUID. Semua string yang digunakan untuk memberi nama jenis dan anggota disimpan dalam tumpukan string. Misalnya, tabel metode tidak secara langsung menyimpan nama metode tertentu, tetapi menunjuk ke nama metode yang disimpan dalam tumpukan string.

Token Metadata

Setiap baris setiap tabel metadata diidentifikasi secara unik dalam bagian CIL file PE dengan token metadata. Token metadata secara konseptual mirip dengan pointer, bertahan di CIL, yang mereferensikan tabel metadata tertentu.

Token metadata adalah angka empat-byte. Byte teratas menunjukkan tabel metadata yang dirujuk token tertentu (metode, jenis, dan sebagainya). Tiga byte yang tersisa menentukan baris dalam tabel metadata yang sesuai dengan elemen pemrograman yang dijelaskan. Jika Anda menentukan metode di C# dan mengkompilasinya ke dalam file PE, token metadata berikut mungkin ada di bagian CIL dari file PE:

0x06000004

Byte teratas (0x06) menunjukkan bahwa ini adalah token MethodDef. Tiga byte yang lebih rendah (000004) memberi tahu runtime bahasa umum untuk melihat baris keempat tabel MethodDef untuk informasi yang menjelaskan definisi metode ini.

Metadata dalam File PE

Ketika program dikompilasi untuk runtime bahasa umum, program dikonversi ke file PE yang terdiri dari tiga bagian. Tabel berikut ini menjelaskan konten setiap bagian.

Bagian PE Konten bagian PE
Header PE Indeks bagian utama file PE dan alamat titik masuk.

Runtime menggunakan informasi ini untuk mengidentifikasi file sebagai file PE dan untuk menentukan di mana eksekusi dimulai saat memuat program ke dalam memori.
Instruksi CIL Instruksi bahasa perantara Microsoft (CIL) yang membentuk kode Anda. Banyak instruksi CIL disertai dengan token metadata.
Metainformasi Tabel dan tumpukan metadata. Runtime menggunakan bagian ini untuk merekam informasi tentang setiap jenis dan anggota dalam kode Anda. Bagian ini juga mencakup atribut kustom dan informasi keamanan.

Penggunaan Run-Time Metadata

Untuk lebih memahami metadata dan perannya dalam runtime bahasa umum, mungkin berguna untuk membangun program sederhana dan menggambarkan bagaimana metadata memengaruhi masa pakainya. Contoh kode berikut menunjukkan dua metode di dalam kelas yang disebut MyApp. Metode Main ini adalah titik masuk program, sementara metode Add hanya mengembalikan jumlah dari dua argumen bilangan bulat.

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

Saat kode berjalan, runtime memuat modul ke dalam memori dan mengkonsultasikan metadata untuk kelas ini. Setelah dimuat, runtime melakukan analisis ekstensif dari aliran bahasa perantara umum (CIL) metode untuk mengonversinya ke instruksi mesin asli yang cepat. Runtime menggunakan kompilator just-in-time (JIT) untuk mengonversi instruksi CIL ke metode kode mesin asli satu per satu sesuai kebutuhan.

Contoh berikut menunjukkan bagian dari CIL yang dihasilkan dari fungsi kode Main sebelumnya. Anda dapat melihat CIL dan metadata dari aplikasi .NET apa pun menggunakan Il 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 */

Pengkompilasi JIT membaca CIL untuk seluruh metode, menganalisisnya secara menyeluruh, dan menghasilkan instruksi asli yang efisien untuk metode tersebut. Pada IL_000d, token metadata untuk Add metode (/*06000003 */) ditemui dan runtime menggunakan token untuk berkonsultasi dengan baris ketiga tabel MethodDef .

Tabel berikut ini memperlihatkan bagian dari tabel MethodDef yang dirujuk oleh token metadata yang menjelaskan metode Add. Meskipun tabel metadata lain ada di rakitan ini dan memiliki nilai uniknya sendiri, hanya tabel ini yang dibahas.

Baris Alamat Virtual Relatif (RVA) ImplFlags Bendera Nama

(Menunjuk ke tumpuk string.)
Tanda tangan (Menunjuk ke tumpukan blob.)
1 0x00002050 Israel

Terkelola
Publik

Gunakan KembaliLot

NamaKhusus

RTNamaKhusus

.ctor
.ctor (konstruktor)
2 0x00002058 Israel

Terkelola
Publik

Statis

Gunakan KembaliLot
Utama string
3 0x0000208c Israel

Terkelola
Publik

Statis

Gunakan KembaliLot
Menambahkan int, int, int

Setiap kolom tabel berisi informasi penting tentang kode Anda. Kolom RVA memungkinkan runtime untuk menghitung alamat memori awal CIL yang menentukan metode ini. Kolom ImplFlags dan Flags berisi bitmask yang menjelaskan metode (misalnya, apakah metodenya publik atau privat). Kolom Nama mengindeks nama metode dari timbunan string. Kolom Tanda Tangan mengindeks definisi tanda tangan metode dalam tumpukan blob.

Runtime menghitung alamat offset yang diinginkan dari kolom RVA di baris ketiga dan mengembalikan alamat ini ke kompiler JIT, yang kemudian melanjutkan ke alamat baru. Pengkompilasi JIT terus memproses CIL di alamat baru sampai menemukan token metadata lain dan prosesnya diulang.

Dengan menggunakan metadata, runtime memiliki akses ke semua informasi yang diperlukan untuk memuat kode Anda dan memprosesnya ke instruksi komputer asli. Dengan cara ini, metadata memungkinkan file yang menjelaskan sendiri dan, bersama dengan sistem jenis umum, pewarisan lintas bahasa.