Bagikan melalui


Kelas System.Reflection.Emit.AssemblyBuilder

Nota

Artikel ini menyediakan keterangan tambahan untuk dokumentasi referensi untuk API ini.

Rakitan dinamis adalah rakitan yang dibuat menggunakan API Reflection Emit. Rakitan dinamis dapat mereferensikan jenis yang ditentukan dalam rakitan dinamis atau statis lainnya. Anda dapat menggunakan AssemblyBuilder untuk menghasilkan rakitan dinamis dalam memori dan menjalankan kodenya selama eksekusi aplikasi yang sama. Di .NET 9 kami menambahkan PersistedAssemblyBuilder baru dengan implementasi reflection emit yang sepenuhnya dikelola, yang memungkinkan Anda menyimpan rakitan (assembly) ke dalam file. Di .NET Framework, Anda dapat melakukan keduanya—menjalankan rakitan dinamis dan menyimpannya ke file. Rakitan dinamis yang dibuat untuk menyimpan disebut rakitan yang bertahan , sementara rakitan khusus memori reguler disebut sementara atau dapat dijalankan. Dalam .NET Framework, rakitan dinamis dapat terdiri dari satu atau beberapa modul dinamis. Di .NET Core dan .NET 5+, rakitan dinamis hanya dapat terdiri dari satu modul dinamis.

Cara Anda membuat AssemblyBuilder instans berbeda untuk setiap implementasi, tetapi langkah-langkah lebih lanjut untuk menentukan modul, jenis, metode, atau enum, dan untuk menulis IL, sangat mirip.

Rakitan dinamis yang dapat dijalankan di .NET

Untuk mendapatkan objek yang dapat AssemblyBuilder dijalankan, gunakan AssemblyBuilder.DefineDynamicAssembly metode . Rakitan dinamis dapat dibuat menggunakan salah satu mode akses berikut:

Mode akses harus ditentukan dengan memberikan nilai AssemblyBuilderAccess yang sesuai dalam panggilan ke metode AssemblyBuilder.DefineDynamicAssembly ketika rakitan dinamis ditentukan dan tidak dapat diubah nanti. Runtime menggunakan mode akses rakitan dinamis untuk mengoptimalkan representasi internal rakitan.

Contoh berikut menunjukkan cara membuat dan menjalankan sebuah assembly:

public void CreateAndRunAssembly(string assemblyPath)
{
    AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("MyAssembly"), AssemblyBuilderAccess.Run);
    ModuleBuilder mob = ab.DefineDynamicModule("MyModule");
    TypeBuilder tb = mob.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);
    MethodBuilder mb = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static,
                                                                   typeof(int), new Type[] {typeof(int), typeof(int)});
    ILGenerator il = mb.GetILGenerator();
    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Ldarg_1);
    il.Emit(OpCodes.Add);
    il.Emit(OpCodes.Ret);

    Type type = tb.CreateType();

    MethodInfo method = type.GetMethod("SumMethod");
    Console.WriteLine(method.Invoke(null, new object[] { 5, 10 }));
}

Rakitan dinamis yang bertahan di .NET

Di .NET, PersistedAssemblyBuilder jenis, yang berasal dari AssemblyBuilder, memungkinkan Anda menyimpan rakitan dinamis. Untuk informasi selengkapnya, lihat skenario penggunaan dan contoh di PersistedAssemblyBuilder.

Rakitan dinamis yang bertahan di .NET Framework

Di .NET Framework, rakitan dan modul dinamis dapat disimpan ke file. Untuk mendukung fitur ini, AssemblyBuilderAccess enumerasi mendeklarasikan dua bidang tambahan: Save dan RunAndSave.

Modul dinamis dalam assembly dinamis yang bisa dipertahankan disimpan ketika assembly dinamis tersebut disimpan menggunakan metode Save. Untuk menghasilkan file eksekusi, metode SetEntryPoint harus dipanggil untuk mengidentifikasi metode yang merupakan titik masuk ke assembly. Rakitan disimpan sebagai DLL secara default, kecuali SetEntryPoint metode meminta pembuatan aplikasi konsol atau aplikasi berbasis Windows.

Contoh berikut menunjukkan cara membuat, menyimpan, dan menjalankan perakitan menggunakan .NET Framework.

public void CreateRunAndSaveAssembly(string assemblyPath)
{
    AssemblyBuilder ab = Thread.GetDomain().DefineDynamicAssembly(new AssemblyName("MyAssembly"), AssemblyBuilderAccess.RunAndSave);
    ModuleBuilder mob = ab.DefineDynamicModule("MyAssembly.dll");
    TypeBuilder tb = mob.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);
    MethodBuilder meb = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static,
                                                                   typeof(int), new Type[] {typeof(int), typeof(int)});
    ILGenerator il = meb.GetILGenerator();
    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Ldarg_1);
    il.Emit(OpCodes.Add);
    il.Emit(OpCodes.Ret);

    Type type = tb.CreateType();

    MethodInfo method = type.GetMethod("SumMethod");
    Console.WriteLine(method.Invoke(null, new object[] { 5, 10 }));
    ab.Save("MyAssembly.dll");
}

Beberapa metode pada kelas dasar Assembly , seperti GetModules dan GetLoadedModules, tidak akan berfungsi dengan benar saat dipanggil dari AssemblyBuilder objek. Anda dapat memuat rakitan dinamis yang ditentukan dan memanggil metode pada rakitan yang dimuat. Misalnya, untuk memastikan bahwa modul sumber daya disertakan dalam daftar modul yang dikembalikan, panggil GetModules pada objek yang dimuat Assembly . Jika rakitan dinamis mengandung lebih dari satu modul, nama file manifes perakitan harus sesuai dengan nama modul yang ditetapkan sebagai argumen pertama metode DefineDynamicModule.

Penandatanganan rakitan dinamis yang menggunakan KeyPair tidak efektif sampai rakitan disimpan ke disk. Jadi, nama kuat tidak akan berfungsi dengan rakitan dinamis yang bersifat sementara.

Rakitan dinamis dapat mereferensikan jenis yang ditentukan dalam rakitan lain. Rakitan dinamis sementara dapat dengan aman mereferensikan jenis yang ditentukan dalam rakitan dinamis sementara lainnya, rakitan dinamis yang dapat dipertahankan, atau rakitan statis. Namun, common language runtime tidak memungkinkan modul dinamis yang persisten untuk mereferensikan tipe yang ditentukan dalam modul dinamis sementara. Ini karena ketika modul dinamis yang bertahan dimuat setelah disimpan ke disk, runtime tidak dapat menyelesaikan referensi ke jenis yang ditentukan dalam modul dinamis sementara.

Pembatasan pemancaran ke domain aplikasi jarak jauh

Beberapa skenario mengharuskan rakitan dinamis dibuat dan dijalankan di domain aplikasi jarak jauh. Pancaran pantulan tidak memungkinkan rakitan dinamis dipancarkan langsung ke domain aplikasi jarak jauh. Solusinya adalah memancarkan rakitan dinamis di domain aplikasi saat ini, menyimpan perakitan dinamis yang dipancarkan ke disk, lalu memuat rakitan dinamis ke domain aplikasi jarak jauh. Dukungan untuk pengendalian jarak jauh dan domain aplikasi hanya tersedia di .NET Framework.