C # Reflection Загрузить внешние библиотеки DLL и все зависимости

Я пытаюсь реализовать (как кажется) чрезвычайно простой механизм внедрения зависимостей для .NET с использованием Reflection. Цель состоит в том, чтобы предоставить интерфейс для класса ServiceFactory и использовать отражение для определения доступных разработчиков этого интерфейса и выбора реализации на основе раздела App.config. Звучит достаточно просто.

Я выбрал путь, который заключается в использовании события после сборки каждого проекта реализации службы для копирования файла .dll реализации в папку «ServiceImplementations». Затем класс ServiceFactory просматривает эту папку, чтобы найти доступных действительных разработчиков интерфейса. Идея состоит в том, что, используя отражение, я должен иметь возможность загружать эту произвольную DLL и все ее зависимости исключительно в отражении во время выполнения. Это цель, которую я хочу достичь.

Где-то в процессе я нормально загружаю эти зависимости. Я могу проверить мои загруженные в настоящее время сборки с помощью var asmDomainAssemblies = AppDomain.CurrentDomain.GetAssemblies ()

Итак, я продолжаю сканирование Reflection и заканчиваю загрузкой зависимых сборок (в данном случае EntityFramework, загружаемых через NuGet, и System.Web.ApplicationServices, системного файла). Все хорошо и хорошо. Пока я не дойду до этой строки кода:

        var serviceImplementationAssembly = CheckLoadedAssemblies(assemblyName);  // This function loads the service implementation assembly and its dependencies
        var appDomainAsm = AppDomain.CurrentDomain.GetAssemblies();
        var implementationTypes = serviceImplementationNamespace.GetTypes();      // Exception here

В последней строке кода создается исключение ReflectionTypeLoadException. Это исключение содержит два LoaderExceptions (каждое FileNotFoundException) с сообщением:

         Could not load file or assembly 'EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. The system cannot find the file specified.":"EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

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

Заранее благодарю за помощь.


person Chris J    schedule 03.12.2012    source источник
comment
Как указано в исключении, это также может быть одна из сборок, от которых зависит EntityFramework, а не сама сборка EntityFramework. Вы можете попробовать Fusion Logviewer: msdn.microsoft.com/en- us / library / e74a18c4.aspx   -  person bitbonk    schedule 03.12.2012
comment
Возможно ли, что вы загрузили сборку EntityFramework динамически, используя Assembly.LoadFrom или Assembly.LoadFile?   -  person Mike Zboray    schedule 03.12.2012
comment
@mikez да, это именно то, что я сделал. Есть ли в этом проблема?   -  person Chris J    schedule 03.12.2012
comment
@bitbonk Проверил сам, других зависимостей нет. EntityFramework - это автономная сборка. В любом случае я запускал Assembly.GetReferencedAssemblies для каждой сборки, которую я загружаю рекурсивно, так что это в любом случае не будет проблемой.   -  person Chris J    schedule 03.12.2012
comment
Вам все равно следует попробовать Fusion Log Viewer, поскольку он может предоставить вам более подробную информацию о любой сбойной привязке сборки.   -  person bitbonk    schedule 03.12.2012
comment
Итак, я запустил Fusion Log Viewer. Когда я устанавливаю средство просмотра журнала на журнал сбоев привязки к диску, я получаю три записи в моем регистраторе при запуске своей программы.   -  person Chris J    schedule 03.12.2012
comment
i.imgur.com/oyt6q.jpg   -  person Chris J    schedule 03.12.2012
comment
Ознакомьтесь с описанием контекстов загрузки Сюзанны Кук   -  person erikkallen    schedule 03.12.2012
comment
Так вы говорите, что некоторые из моих загруженных сборок находятся в другом контексте привязки? Возможно, потому, что я использовал Assembly.Load для системных сборок и Assembly.LoadFile для реализации сервисов? Как мне это проверить? Все они находятся в текущем домене приложений.   -  person Chris J    schedule 03.12.2012


Ответы (1)


Наконец-то я заставил его работать. По сути, я пытался обработать событие AssemblyResolve вручную, загружая каждую сборку, проверяя ее зависимости и запуская события Assembly.Load и Assembly.LoadFile, когда мне было угодно. Когда я добавил событие CurrentDomain_AssemblyResolve, которое при запуске запускало мой собственный код поиска / загрузки сборки в каталоге, все просто работало.

Из-за некоторой внутренней проблемы AppDomain / BundleContext возникло исключение. Переход на AssemblyResolve устранил мою проблему. К сожалению, это все, что я знаю о том, что произошло. Я приму ответ, если кто-нибудь сможет объяснить, что здесь творится под прикрытием.

person Chris J    schedule 03.12.2012
comment
Это именно то, что я бы предложил. В документации описывается это поведение (msdn.microsoft.com /en-us/library/1009fa28(v=vs.110).aspx) with Если сборка загружается с помощью LoadFrom, а затем сборка в контексте загрузки пытается загрузить ту же сборку по отображаемому имени, попытка загрузки не удалась. но если вы еще не знаете об этой проблеме, это мало помогает. - person Mike Zboray; 03.12.2012