Share via


Anvisningar: Granska sammansättningsinnehåll med metadataLoadContext

Reflektions-API:et i .NET gör det som standard möjligt för utvecklare att inspektera innehållet i sammansättningar som läses in i huvudkörningskontexten. Ibland går det dock inte att läsa in en sammansättning i körningskontexten, till exempel för att den kompilerats för en annan plattform eller processorarkitektur, eller så är det en referenssammansättning. Med API:et System.Reflection.MetadataLoadContext kan du läsa in och inspektera sådana sammansättningar. Sammansättningar som läses in i MetadataLoadContext behandlas endast som metadata, dvs. du kan undersöka typer i sammansättningen, men du kan inte köra någon kod som finns i den. Till skillnad från huvudkörningskontexten MetadataLoadContext läses inte beroendena in automatiskt från den aktuella katalogen. I stället används den anpassade bindningslogik som tillhandahålls av den MetadataAssemblyResolver som skickas till den.

Förutsättningar

Om du vill använda MetadataLoadContextinstallerar du NuGet-paketet System.Reflection.MetadataLoadContext . Det stöds i alla .NET Standard 2.0-kompatibla målramverk, till exempel .NET Core 2.0 eller .NET Framework 4.6.1.

Skapa MetadataAssemblyResolver för MetadataLoadContext

För att MetadataLoadContext skapa måste du ange instansen MetadataAssemblyResolverav . Det enklaste sättet att ange ett är att använda PathAssemblyResolver, som löser sammansättningar från den angivna samlingen med strängar för sammansättningssökväg. Den här samlingen, förutom sammansättningar som du vill inspektera direkt, bör även innehålla alla nödvändiga beroenden. Om du till exempel vill läsa det anpassade attributet som finns i en extern sammansättning bör du inkludera den sammansättningen eller så genereras ett undantag. I de flesta fall bör du inkludera åtminstone kärnsammansättningen, dvs. sammansättningen som innehåller inbyggda systemtyper, till exempel System.Object. Följande kod visar hur du skapar PathAssemblyResolver med hjälp av samlingen som består av den inspekterade sammansättningen och den aktuella körningens kärnsammansättning:

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

Om du behöver åtkomst till alla BCL-typer kan du inkludera alla körningssammansättningar i samlingen. Följande kod visar hur du skapar PathAssemblyResolver med hjälp av samlingen som består av den inspekterade sammansättningen och alla sammansättningar av den aktuella körningen:

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

Skapa metadataLoadContext

Om du vill skapa MetadataLoadContextanropar du konstruktorn MetadataLoadContext(MetadataAssemblyResolver, String)och skickar den tidigare skapade MetadataAssemblyResolver som den första parametern och kärnsammansättningens namn som den andra parametern. Du kan utelämna huvudsammansättningens namn, i vilket fall konstruktorn försöker använda standardnamnen: "mscorlib", "System.Runtime" eller "netstandard".

När du har skapat kontexten kan du läsa in sammansättningar i den med metoder som LoadFromAssemblyPath. Du kan använda alla reflektions-API:er för inlästa sammansättningar förutom de som omfattar kodkörning. Metoden GetCustomAttributes omfattar körning av konstruktorer, så använd GetCustomAttributesData metoden i stället när du behöver undersöka anpassade attribut i MetadataLoadContext.

Följande kodexempel skapar MetadataLoadContext, läser in sammansättningen i den och matar ut sammansättningsattribut till konsolen:

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

Om du behöver testa typer för MetadataLoadContext likhet eller tilldelning kan du bara använda typobjekt som lästs in i den kontexten. Det går inte att blanda MetadataLoadContext typer med körningstyper. Överväg till exempel en typ testedType i MetadataLoadContext. Om du behöver testa om en annan typ kan tilldelas från den ska du inte använda kod som typeof(MyType).IsAssignableFrom(testedType). Använd kod som den här i stället:

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

Exempel

Ett fullständigt kodexempel finns i exemplet Granska sammansättningsinnehåll med metadataLoadContext.

Se även