Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
API отражения в .NET по умолчанию позволяет разработчикам проверять содержимое сборок, загруженных в основной контекст выполнения. Однако иногда невозможно загрузить сборку в контекст выполнения, например, так как она была скомпилирована для другой архитектуры платформы или процессора, или это эталонная сборка. System.Reflection.MetadataLoadContext API позволяет загружать и проверять такие сборки. Сборки, загруженные в него MetadataLoadContext , обрабатываются только как метаданные, т. е. можно изучить типы в сборке, но вы не можете выполнить в ней код, содержащийся в нем. В отличие от основного контекста выполнения, MetadataLoadContext не загружает зависимости автоматически из текущего каталога; вместо этого используется пользовательская логика привязки, предоставляемая переданным ему MetadataAssemblyResolver.
Предпосылки
Чтобы использовать MetadataLoadContext, установите пакет NuGet System.Reflection.MetadataLoadContext . Она поддерживается в любой целевой платформе, совместимой с .NET Standard 2.0, например .NET Core 2.0 или .NET Framework 4.6.1.
Создание метаданныхAssemblyResolver для MetadataLoadContext
Для создания MetadataLoadContext необходимо предоставить экземпляр MetadataAssemblyResolver. Самый простой способ предоставить объект — использовать PathAssemblyResolver, который обрабатывает сборки из заданной коллекции строк с путями к сборкам. Эта коллекция, помимо сборок, которые требуется проверить напрямую, также должна включать все необходимые зависимости. Например, чтобы прочитать настраиваемый атрибут, расположенный во внешней сборке, следует включить эту сборку, иначе произойдет выброс исключения. В большинстве случаев следует включить по крайней мере основную сборку, то есть сборку, содержащую встроенные системные типы, например System.Object. В следующем коде показано, как создать PathAssemblyResolver, используя коллекцию, состоящую из проверенной сборки и основной сборки текущей среды выполнения:
var resolver = new PathAssemblyResolver(new string[] { "ExampleAssembly.dll", typeof(object).Assembly.Location });
Если вам нужен доступ ко всем типам BCL, можно включить все сборки среды выполнения в коллекцию. В следующем коде показано, как создать коллекцию PathAssemblyResolver , состоящую из проверенной сборки и всех сборок текущей среды выполнения:
// 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);
Создание MetadataLoadContext
Чтобы создать MetadataLoadContext, вызовите его конструктор MetadataLoadContext(MetadataAssemblyResolver, String), передав ранее созданный MetadataAssemblyResolver в качестве первого параметра и имя основной сборки в качестве второго параметра. Вы можете опустить имя основной сборки, в этом случае конструктор попытается использовать имена по умолчанию: "mscorlib", "System.Runtime" или "netstandard".
После создания контекста можно загрузить сборки в него с помощью таких методов, как LoadFromAssemblyPath. Вы можете использовать все API отражения для загруженных сборок, кроме тех, которые включают выполнение кода. Метод GetCustomAttributes включает выполнение конструкторов, поэтому используйте GetCustomAttributesData метод вместо того, когда необходимо проверить пользовательские атрибуты в объекте MetadataLoadContext.
Следующий пример кода создает MetadataLoadContext, загружает сборку в нее и выводит атрибуты сборки в консоль:
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}");
}
}
}
Если необходимо протестировать типы на MetadataLoadContext равенство или присваиваемость, используйте только объекты типов, загруженные в этот контекст.
MetadataLoadContext Смешивание типов с типами среды выполнения не поддерживается. Например, рассмотрим тип testedType в MetadataLoadContext. Если вам нужно проверить, можно ли присвоить ему другой тип, не используйте код, например, typeof(MyType).IsAssignableFrom(testedType). Используйте следующий код:
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
Полный пример кода см. в примере "Проверка содержимого сборки" с помощью примера MetadataLoadContext.