Bagikan melalui


Cara: Memeriksa isi assembly menggunakan MetadataLoadContext

API refleksi di .NET secara default memungkinkan pengembang untuk memeriksa konten assembly yang dimuat ke dalam konteks eksekusi utama. Namun, terkadang memuat assembly ke dalam konteks eksekusi tidak dapat dilakukan. Misalnya, karena dikompilasi untuk platform atau arsitektur prosesor lain, atau berupa assembly referensi. System.Reflection.MetadataLoadContext API memungkinkan Anda memuat dan memeriksa assembly tersebut. Assembly yang dimuat ke dalam MetadataLoadContext diperlakukan hanya sebagai metadata. Anda dapat memeriksa jenis dalam assembly, tetapi Anda tidak dapat menjalankan kode apa pun yang terkandung di dalamnya. Tidak seperti konteks eksekusi utama, MetadataLoadContext tidak otomatis memuat dependensi dari direktori saat ini; sebaliknya menggunakan logika pengikatan kustom yang disediakan oleh MetadataAssemblyResolver yang diteruskan ke direktori tersebut.

Prasyarat

Untuk menggunakan MetadataLoadContext, instal paket NuGet System.Reflection.MetadataLoadContext. Hal ini didukung pada kerangka kerja target yang mematuhi .NET Standard 2.0. Misalnya, .NET Core 2.0 atau .NET Framework 4.6.1.

Membuat MetadataAssemblyResolver untuk MetadataLoadContext

Membuat persyaratan MetadataLoadContext yang menyediakan instans MetadataAssemblyResolver. Cara paling sederhana untuk menyediakannya adalah dengan menggunakan PathAssemblyResolver, yang menyelesaikan assembly dari koleksi string jalur assembly yang diberikan. Koleksi ini, selain assembly yang ingin Anda periksa secara langsung, juga harus menyertakan semua dependensi yang diperlukan. Misalnya, untuk membaca atribut kustom yang terletak di assembly eksternal, Anda harus menyertakan assembly tersebut atau pengecualian akan dilemparkan. Dalam kebanyakan kasus, Anda harus menyertakan setidaknya assembly inti, yaitu, assembly yang berisi jenis sistem bawaan, seperti System.Object. Kode berikut menunjukkan cara membuat PathAssemblyResolver menggunakan koleksi yang terdiri dari assembly yang diperiksa dan assembly inti runtime saat ini:

var resolver = new PathAssemblyResolver(new string[] { "ExampleAssembly.dll", typeof(object).Assembly.Location });

Jika Anda memerlukan akses ke semua jenis BCL, Anda dapat menyertakan semua assembly runtime dalam koleksi. Kode berikut menunjukkan cara membuat PathAssemblyResolver menggunakan koleksi yang terdiri dari assembly yang diperiksa dan semua assembly runtime saat ini:

// Get the array of runtime assemblies.
string[] runtimeAssemblies = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll");

// Create the list of assembly paths consisting of runtime assemblies and the inspected assembly.
var paths = new List<string>(runtimeAssemblies);
paths.Add("ExampleAssembly.dll");

// Create PathAssemblyResolver that can resolve assemblies using the created list.
var resolver = new PathAssemblyResolver(paths);

Membuat MetadataLoadContext

Untuk membuat MetadataLoadContext, panggil konstruktornya MetadataLoadContext(MetadataAssemblyResolver, String), meneruskan MetadataAssemblyResolver yang sebelumnya dibuat sebagai parameter pertama dan nama assembly inti sebagai parameter kedua. Anda dapat menghilangkan nama assembly inti, dalam hal ini konstruktor akan mencoba menggunakan nama default: "mscorlib", "System.Runtime", atau "netstandard".

Setelah membuat konteks, Anda dapat memuat assembly ke dalamnya menggunakan metode seperti LoadFromAssemblyPath. Anda dapat menggunakan semua API pantulan pada assembly yang dimuat kecuali yang melibatkan eksekusi kode. Metode GetCustomAttributes ini memang melibatkan eksekusi konstruktor, jadi gunakan metode GetCustomAttributesData sebagai gantinya ketika Anda perlu memeriksa atribut kustom di MetadataLoadContext.

Sampel kode berikut membuat MetadataLoadContext, memuat assembly ke dalamnya, dan menghasilkan atribut assembly ke dalam konsol:

var mlc = new MetadataLoadContext(resolver);

using (mlc)
{
    // Load assembly into MetadataLoadContext.
    Assembly assembly = mlc.LoadFromAssemblyPath("ExampleAssembly.dll");
    AssemblyName name = assembly.GetName();

    // Print assembly attribute information.
    Console.WriteLine($"{name.Name} has following attributes: ");

    foreach (CustomAttributeData attr in assembly.GetCustomAttributesData())
    {
        try
        {
            Console.WriteLine(attr.AttributeType);
        }
        catch (FileNotFoundException ex)
        {
            // We are missing the required dependency assembly.
            Console.WriteLine($"Error while getting attribute type: {ex.Message}");
        }
    }
}

Jika Anda perlu menguji jenis untuk kesetaraan atau tugas, hanya gunakan objek jenis yang dimuat MetadataLoadContext ke dalam konteks tersebut. Jenis pencampuran MetadataLoadContext dengan jenis runtime tidak didukung. Misalnya, pertimbangkan jenis testedType di MetadataLoadContext. Jika Anda perlu menguji apakah jenis lain dapat ditetapkan darinya, jangan gunakan kode seperti typeof(MyType).IsAssignableFrom(testedType). Gunakan kode seperti ini sebagai gantinya:

Assembly matchAssembly = mlc.LoadFromAssemblyPath(typeof(MyType).Assembly.Location);
Type matchType = assembly.GetType(typeof(MyType).FullName!)!;

if (matchType.IsAssignableFrom(testedType))
{
    Console.WriteLine($"{nameof(matchType)} is assignable from {nameof(testedType)}");
}

Contoh

Untuk contoh kode lengkap, lihat sampel Periksa konten assembly menggunakan MetadataLoadContext.

Lihat juga