Instrukcje: sprawdzanie zawartości zestawu przy użyciu elementu MetadataLoadContext

Interfejs API odbicia na platformie .NET domyślnie umożliwia deweloperom sprawdzanie zawartości zestawów załadowanych do głównego kontekstu wykonywania. Jednak czasami nie można załadować zestawu do kontekstu wykonywania, na przykład dlatego, że został skompilowany dla innej platformy lub architektury procesora lub jest zestawem odniesienia. Interfejs System.Reflection.MetadataLoadContext API umożliwia ładowanie i sprawdzanie takich zestawów. Zestawy załadowane do MetadataLoadContext elementu są traktowane tylko jako metadane, czyli można badać typy w zestawie, ale nie można wykonać żadnego zawartego w nim kodu. W przeciwieństwie do kontekstu głównego wykonywania, MetadataLoadContext zależności nie są automatycznie ładowane z bieżącego katalogu. Zamiast tego używa niestandardowej logiki powiązania dostarczonej MetadataAssemblyResolver przez przekazany do niego.

Wymagania wstępne

Aby użyć programu MetadataLoadContext, zainstaluj plik System.EmocjeJonów. MetadataLoadContext pakiet NuGet. Jest ona obsługiwana w dowolnej strukturze docelowej zgodnej ze standardem .NET Standard 2.0, na przykład .NET Core 2.0 lub .NET Framework 4.6.1.

Tworzenie elementu MetadataAssemblyResolver dla elementu MetadataLoadContext

MetadataLoadContext Utworzenie elementu wymaga podania wystąpienia klasy MetadataAssemblyResolver. Najprostszym sposobem udostępnienia elementu jest użycie PathAssemblyResolverelementu , który rozpoznaje zestawy z danej kolekcji ciągów ścieżki zestawu. Ta kolekcja, oprócz zestawów, które mają być sprawdzane bezpośrednio, powinna również zawierać wszystkie potrzebne zależności. Na przykład aby odczytać atrybut niestandardowy znajdujący się w zestawie zewnętrznym, należy uwzględnić ten zestaw lub wyjątek. W większości przypadków należy uwzględnić co najmniej podstawowy zestaw, czyli zestaw zawierający wbudowane typy systemu, takie jak System.Object. Poniższy kod pokazuje, jak utworzyć PathAssemblyResolver przy użyciu kolekcji składającej się z kontrolowanego zestawu i podstawowego zestawu bieżącego środowiska uruchomieniowego:

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

Jeśli potrzebujesz dostępu do wszystkich typów listy BCL, możesz uwzględnić wszystkie zestawy środowiska uruchomieniowego w kolekcji. Poniższy kod pokazuje, jak utworzyć PathAssemblyResolver przy użyciu kolekcji składającej się ze sprawdzonego zestawu i wszystkich zestawów bieżącego środowiska uruchomieniowego:

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

Tworzenie elementu MetadataLoadContext

Aby utworzyć element , wywołaj MetadataLoadContextjego konstruktor MetadataLoadContext(MetadataAssemblyResolver, String), przekazując wcześniej utworzony MetadataAssemblyResolver jako pierwszy parametr i podstawową nazwę zestawu jako drugi parametr. Możesz pominąć podstawową nazwę zestawu, w tym przypadku konstruktor spróbuje użyć nazw domyślnych: "mscorlib", "System.Runtime" lub "netstandard".

Po utworzeniu kontekstu można załadować do niego zestawy przy użyciu metod takich jak LoadFromAssemblyPath. Można użyć wszystkich interfejsów API odbicia w załadowanych zestawach z wyjątkiem tych, które obejmują wykonywanie kodu. Metoda GetCustomAttributes obejmuje wykonywanie konstruktorów, więc zamiast tego należy użyć GetCustomAttributesData metody , gdy trzeba zbadać atrybuty niestandardowe w obiekcie MetadataLoadContext.

Poniższy przykładowy kod tworzy MetadataLoadContextelement , ładuje do niego zestaw i generuje atrybuty zestawu do konsoli:

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

Jeśli chcesz przetestować typy w programie pod MetadataLoadContext kątem równości lub możliwości przypisywania, użyj tylko obiektów typu załadowanych do tego kontekstu. Mieszanie MetadataLoadContext typów z typami środowiska uruchomieniowego nie jest obsługiwane. Rozważmy na przykład typ testedType w pliku MetadataLoadContext. Jeśli musisz sprawdzić, czy inny typ można z niego przypisać, nie używaj kodu takiego jak typeof(MyType).IsAssignableFrom(testedType). Użyj kodu w następujący sposób:

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

Przykład

Pełny przykład kodu można znaleźć w przykładzie Inspekcja zawartości zestawu przy użyciu elementu MetadataLoadContext.

Zobacz też