Postupy: Kontrola obsahu sestavení pomocí metadataLoadContext

Reflexní API v .NET ve výchozím nastavení umožňuje vývojářům kontrolovat obsah sestavení načtených do hlavního kontextu spuštění. Někdy ale není možné načíst sestavení do kontextu spuštění, například protože byl zkompilován pro jinou platformu nebo architekturu procesoru nebo je to referenční sestavení. Rozhraní System.Reflection.MetadataLoadContext API umožňuje načíst a prozkoumat takové assembly. Sestavení načtená do objektu MetadataLoadContext jsou považována pouze za metadata, to znamená, že můžete zkoumat typy v sestavení, ale nemůžete spustit žádný kód obsažený v něm. Na rozdíl od hlavního kontextu spuštění MetadataLoadContext automaticky nenačítá závislosti z aktuálního adresáře; místo toho používá vlastní logiku vazby poskytovanou objektem MetadataAssemblyResolver.

Požadavky

Chcete-li použít MetadataLoadContext, nainstalujte balíček NuGet System.Reflection.MetadataLoadContext . Je podporován na jakémkoli cílovém rozhraní kompatibilním s .NET Standard 2.0, například .NET Core 2.0 nebo .NET Framework 4.6.1.

Vytvořte MetadataAssemblyResolver pro MetadataLoadContext

MetadataLoadContext Vytvoření vyžaduje poskytnutí instance objektu MetadataAssemblyResolver. Nejjednodušší způsob, jak poskytnout cestu, je použít PathAssemblyResolver, který řeší sestavení z dané kolekce řetězců cest k sestavením. Tato kolekce by kromě sestavení, která chcete zkontrolovat přímo, měla obsahovat také všechny potřebné závislosti. Pokud chcete například přečíst vlastní atribut umístěný v externím sestavení, měli byste toto sestavení zahrnout, jinak bude vyvolána výjimka. Ve většině případů byste měli zahrnout alespoň základní sestavení, tj. sestavení obsahující předdefinované systémové typy, například System.Object. Následující kód ukazuje, jak vytvořit PathAssemblyResolver pomocí kolekce skládající se ze zkoumaného sestavení a jádrového sestavení aktuálního runtime.

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

Pokud potřebujete přístup ke všem typům BCL, můžete do kolekce přidat všechna sestavení modulu runtime. Následující kód ukazuje, jak vytvořit PathAssemblyResolver pomocí kolekce sestávající z prověřeného sestavení a všech sestavení aktuálně běžícího modulu runtime.

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

Vytvoření MetadataLoadContext

Chcete-li vytvořit MetadataLoadContext, vyvolejte jeho konstruktor MetadataLoadContext(MetadataAssemblyResolver, String), předejte dříve vytvořené MetadataAssemblyResolver jako první parametr a název hlavní assembly jako druhý parametr. Můžete vynechat název základního sestavení, v takovém případě se konstruktor pokusí použít výchozí názvy: "mscorlib", "System.Runtime" nebo "netstandard".

Po vytvoření kontextu do něj můžete načíst sestavení pomocí metod, jako je LoadFromAssemblyPath. Na načtených sestaveních můžete použít všechny reflexní API s výjimkou těch, které zahrnují provádění kódu. Tato GetCustomAttributes metoda zahrnuje provádění konstruktorů, takže místo toho použijte metodu GetCustomAttributesData , pokud potřebujete prozkoumat vlastní atributy v souboru MetadataLoadContext.

Následující ukázka kódu vytvoří MetadataLoadContext, načte sestavení do něj a zapíše atributy sestavení na konzoli.

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

Pokud potřebujete testovat typy MetadataLoadContext pro rovnost nebo přiřaditelnost, použijte pouze objekty typu načtené do tohoto kontextu. Kombinování MetadataLoadContext typů s typy modulu runtime se nepodporuje. Představte si například typ testedType v MetadataLoadContext. Pokud potřebujete otestovat, jestli je z něj možné přiřadit jiný typ, nepoužívejte kód jako typeof(MyType).IsAssignableFrom(testedType). Místo toho použijte kód podobný tomuto:

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

Example

Úplný příklad kódu naleznete v části Kontrola obsahu sestavení pomocí ukázky MetadataLoadContext.

Viz také