Динамическая загрузка сборок и их зависимостей с использованием развертывания XCOPY

У меня есть загрузчик приложений, который динамически загружает приложения. Приложение представляет собой сборку со всеми зависимыми элементами в одной папке. Используя развертывание XCOPY, я могу добавлять / удалять приложения, копируя / удаляя папку. Чтобы упростить стандартную привязку сборки.NET, я копирую папки приложения в корзину загрузчика. Я установил зондирующий privatePath в конфигурационном файле, и все работает как шарм.

В приложениях используется фреймворк, то есть общие сборки как зависимые.

Теперь у меня есть требование, согласно которому каждое приложение должно иметь возможность использовать свою собственную версию фреймворка.

Это прекрасно работает, когда я устанавливаю версии фреймворка в GAC, и разные версии сборки просто отлично загружаются в AppDomain по умолчанию.

Теперь я хочу вернуться к своему решению XCOPY и скопировать правильные версии фреймворка в их соответствующие папки приложений и разрывы решения.

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

Как будто загрузчик.NET перестает проверять после первого совпадения сборки с папкой в ​​"privatePath" и не смотрит дальше.

Любые идеи о том, как вести себя так же, как при использовании GAC? Что-нибудь еще, что я мог указать в конфиге, codeBase? (без абсолютных путей к файлам, пожалуйста).

кр, мишель

2 ответа

Согласно этой статье о сборках:

Вы также должны помнить, что CLR просматривает предопределенную последовательность каталогов во время исследования. Учитывая значение privatePath MyAssemblies, CLR теперь будет проверять сборку с именем MyLibrary в следующем порядке:

C:/Apps/MyLibrary.DLL
C:/Apps/MyLibrary/MyLibrary.DLL
C:/Apps/MyAssemblies/MyLibrary.DLL
C:/Apps/MyAssemblies/MyLibrary/MyLibrary.DLL
C:/Apps/MyLibrary.EXE
C:/Apps/MyLibrary/MyLibrary.EXE
C:/Apps/MyAssemblies/MyLibrary.EXE
C:/Apps/MyAssemblies/MyLibrary/MyLibrary.EXE

Последовательность путей к файлам, в которых CLR проверяет файл сборки, важна, поскольку процесс проверки останавливается, когда CLR находит файл сборки с правильным именем файла. Если вы развернете приложение вместе с одной версией MyLibrary.dll в каталоге ApplicationBase и второй версией в подкаталоге MyAssemblies, какой файл DLL будет загружен в CLR? Вы должны увидеть, что CLR собирается загрузить DLL в каталог ApplicationBase, потому что это всегда первый каталог, в котором CLR выполняет поиск во время процесса проверки.

Обновить:

Проверьте этот пост. Это касается более или менее той же проблемы, что и вы.

Вам повезет больше, если вы используете Assembly.LoadFrom для загрузки всех сборок, которые вы найдете в этих папках.

Это меняет поведение при проверке и позволяет среде выполнения выполнять локальный поиск туда, откуда изначально была загружена сборка, чтобы найти ее ссылки. Вы получите общий доступ к версии фреймворка на уровне сборки.

То есть:

  • Приложение "а" загружается, вызывая загрузку Framework v1.02.
  • Приложение 'b' загружается, вызывая загрузку Framework v1.01.
  • Приложение "c" загружается, связано с Framework v1.02 и просто повторно использует код, который был загружен после загрузки приложения "a".

Тем не менее, это решение может быть бесполезным, если вы явно не загружаете сборки.

В этом случае - я бы пошел с решением в ответе, упомянутом Янником М. - подключитесь к событию AssemblyResolve; сохраняйте некоторое статическое состояние, когда вы начинаете загружать приложение, чтобы ваш обработчик событий знал, какое приложение загружается; и если какая-либо сборка не может быть решена, вы можете посмотреть на это состояние, чтобы определить, где он должен искать, и загрузить сборку оттуда.

Другие вопросы по тегам