Проверка типов через MetadataLoadContext не выполнена из-за отсутствия сборки (. NET ядро) - PullRequest
1 голос
/ 12 февраля 2020

Я хочу проверить сборки, если они имеют указанный тип c без загрузки сборки в текущей области, которая доступна через MetadataLoadContext в. NET Core 3.

Но если я попробую В следующем примере

internal static class Program
{
    // ReSharper disable once UnusedParameter.Local
    private static void Main(string[] args)
    {
        var paths = new string[] { @"Plugin.dll" };
        var resolver = new PathAssemblyResolver(paths);
        var pluginInterface = typeof(IPlugin);
        using (var context = new MetadataLoadContext(resolver))
        {
            var assembly =
                context.LoadFromAssemblyName(@"Plugin");
            foreach (var type in assembly.GetTypes())
            {
                if (type.IsClass && pluginInterface.IsAssignableFrom(type))
                    Console.WriteLine("found");
            }
        }
    }
}

получено исключение

System.IO.FileNotFoundException: не удалось найти сборку ядра. Укажите допустимое имя сборки ядра в конструкторе MetadataLoadContext или предоставьте MetadataAssemblyResolver, который может загрузить сборку ядра.

в var context = new MetadataLoadContext(resolver)

Что подразумевается под сборкой ядра? Или что я делаю не так? https://blog.vincentbitter.nl/net-core-3-0/, кажется, не работает для меня.

Ответы [ 2 ]

1 голос
/ 19 марта 2020

Существующий ответ не работал для меня (. NET Core 2.1). Сбой с ошибкой, что System.Runtime не найден. Если я жестко запрограммировал полный путь к System.Runtime, он не работает для других сборок, таких как System.Private.CoreLib. Также проверка типов через IsAssignableFrom, кажется, не работает, когда один тип не из MetadataLoadContext.

Возможным решением для ошибок загрузки сборок является включение всех сборок BCL (все файлы DLL в каталоге, возвращаемые RuntimeEnvironment.GetRuntimeDirectory ). Это выглядит несколько глупо, потому что не все они на самом деле являются управляемыми сборками, но, похоже, это работает. Вот полный пример поиска типов, которые реализуют интерфейс через MetadataLoadContext:

using System;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;

namespace MetadataLoadContextSample
{
    class Program
    {
        static int Main(string[] args)
        {
            string inputFile = @"Plugin.dll";

            string[] runtimeAssemblies = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll");                        
            var paths = new List<string>(runtimeAssemblies);
            paths.Add(inputFile);            
            var resolver = new PathAssemblyResolver(paths);
            var context = new MetadataLoadContext(resolver);

            using (context)
            {                
                Assembly assembly = context.LoadFromAssemblyPath(inputFile);
                AssemblyName name = assembly.GetName();

                foreach (TypeInfo t in assembly.GetTypes())
                {
                    try
                    {
                        if (t.IsClass && t.GetInterface("IPlugin") != null)
                        {
                            Console.WriteLine(t.Name);
                        }
                    }
                    catch (FileNotFoundException ex)
                    {                        
                        Console.WriteLine("FileNotFoundException: " + ex.Message);
                    }
                    catch (TypeLoadException ex)
                    {
                        Console.WriteLine("TypeLoadException: " + ex.Message);
                    }
                }
            }

            Console.ReadLine();
            return 0;
        }
    }
}
0 голосов
/ 13 февраля 2020

Предоставление следующих путей к. NET core libs works

  var paths = new string[] {@"Plugin.dll", @"netstandard.dll", "System.Runtime.dll"};
...