Assembly.GetTypes () - ReflectionTypeLoadException - PullRequest
14 голосов
/ 17 апреля 2010

Мы внедряем инфраструктуру плагинов для нашего приложения и загружаем сборки плагинов, используя Assembly.Loadfrom. Затем мы используем GetTypes () и дополнительно исследуем типы с каждым файлом плагина для поддерживаемых интерфейсов.

Путь к плагинам предоставляется пользователем, и мы перебираем каждый из файлов в папке, чтобы посмотреть, поддерживает ли он (плагин) наш интерфейс плагина. Если это так, мы создаем экземпляр, если нет, мы переходим к следующему файлу.

Мы строим две версии программного обеспечения из одной базы кода (appA_1 и appA_2).

Загрузка плагинов работает хорошо, когда плагины загружаются приложением, которое было создано одновременно с файлом плагина. Однако если мы создаем appA_2 и указываем на папку плагинов appA_1, мы получаем исключение при вызове GetTypes ().

Базовая версия нашего кода:

var pluginAssembly = Assembly.LoadFrom(FileName);    
foreach (var pluginType in pluginAssembly.GetTypes())
{

Мы получаем исключение «ReflectionTypeLoadException».

Это связано с тем, что мы хотим, чтобы наше приложение могло загружать типы любого плагина, созданного кем-либо. Нам чего-то не хватает?

EDIT: После итерации исключений LoaderException мы обнаружили, что существует один файл libPublic.dll, который генерирует исключение System.IO.FileNotFoundException. Странно то, что этот файл находится в каталоге приложения, а плагин связан с файлом проекта.

РЕДАКТИРОВАТЬ 2: В журнале исключений мы находим следующее «Сравнение имени сборки привело к несоответствию: номер редакции»

Ответы [ 3 ]

15 голосов
/ 17 апреля 2010

Несколько вещей:

  • Убедитесь, что у вас нет дубликатов сборок в каталоге плагинов (т.е. сборок, которые вы уже загружаете в свое основное приложение из каталога приложений). В противном случае, когда вы загружаете свой плагин, он может загрузить дополнительная копия той же сборки. Это может привести к забавным исключениям, таким как:

    Объект (типа «MyObject») не относится к типу «MyObject».

  • Если вы получаете исключение при создании экземпляра типа, вам может потребоваться обработать AppDomain.AssemblyResolve:

    private void App_Startup(object sender, StartupEventArgs e)
    {
        // Since we'll be dynamically loading assemblies at runtime, 
        // we need to add an appropriate resolution path
        // Otherwise weird things like failing to instantiate TypeConverters will happen
        AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
    }
    
    private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        var domain = (AppDomain) sender;
    
        foreach (var assembly in domain.GetAssemblies())
        {
            if (assembly.FullName == args.Name)
            {
                return assembly;
            }
        }
    
        return null;
    }
    

Я понимаю, что немного странно говорить CLR, что для разрешения сборки найдите сборку с именем, которое мы используем для разрешения, но я видел странные вещи, происходящие без него. Например, я мог бы создавать экземпляры типов из сборки плагина, но если бы я попытался использовать TypeDescriptor.GetConverter, он не нашел бы TypeConverter для класса, даже если бы он мог видеть атрибут Converter в классе.


Глядя на ваши правки, это, вероятно, не является причиной вашего текущего исключения, хотя вы можете столкнуться с этими проблемами позже, когда будете работать с плагинами.

2 голосов
/ 27 марта 2012

Благодаря этому посту я смог решить ReflectionTypeLoadException, который я получал в UITypeEditor. Это сборка конструктора (смарт-тег winforms, используемый во время разработки) пользовательской библиотеки классов, которая сканирует некоторые типы.

/// <summary>
/// Get the types defined in the RootComponent.
/// </summary>
private List<Type> getAssemblyTypes(IServiceProvider provider)
{
    var types = new List<Type>();
    try
    {
        IDesignerHost host = (IDesignerHost)provider.GetService(typeof(IDesignerHost));
        ITypeResolutionService resolution = (ITypeResolutionService)provider.GetService(typeof(ITypeResolutionService));
        AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
        {
            foreach (var assembly in ((AppDomain)sender).GetAssemblies())
            {
                if (assembly.FullName == args.Name)
                {
                    return assembly;
                }
            }

            return null;
        };

        Type rootComponentType = resolution.GetType(host.RootComponentClassName, false);
        types = rootComponentType.Assembly.GetTypes().ToList();
    }
    catch
    {
    }

    return types;
}
0 голосов
/ 25 декабря 2010

Вы получаете несоответствие версии сборки. Поскольку ваши плагины ссылаются на этот libPublic.dll, вы должны тщательно его версия и, в частности, не повышать его ревизию / сборку / и т.д. числа на каждой компиляции.

...