2009-07-27 4 views
6

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

У меня есть две сборки (ZA & ZB), оба из которых указывают на общий проект/dll (ZC), но которые могут быть на другой версии (то же самое имя DLL, те же пространства имен, некоторые классы могут быть разными) , Однако каждая сборка работает сама по себе, если одна загружается другой во время выполнения (например, A загружает B), то я не могу заставить ее работать. Нужна помощь.

Вот установка:

  • ZA зависит от ZC (общая) версия 1.1
  • ZB зависит от ZC версии 1,0

ZA необходимо загрузить потребности загружать что-то в ZB (который зависит от ZC), во время выполнения.

ZA - главное приложение. В каталоге bin есть каталог плагинов plugins/plugin-ZB, под которым я хотел бы разместить все ZB и его зависимости (ZC).

Вот что я пытался до сих пор:

Assembly.Load() используя ту же версию DLL - работал отлично.

Assembly.Load() с использованием различных версий dll - ZB загружается, но когда метод запускается, я получаю исключение метода, которое не найдено.

AppDomain.Load() получил сообщенный файл не найден; Я даже использовал делегата для разрешения сборок.

Некоторые сведения о ZC: - некоторые методы являются публичными (некоторые из них не являются). Например. Log.Log("hello"); - некоторые могут возвращать значения (примитивы или объекты). - некоторые методы не статичны (и возвращают значения).

Помощь? - TIA

ответ

1

Помимо превосходного совета Джонатана Аллена, более «классический» способ решить проблему - загрузить 2 версии в 2 разных AppDomanis. Затем вы можете использовать .NET Remoting для того, чтобы сделать двумя партнерами из AppDomains. Поэтому ZA должна создать новый Appdomain, загрузить в этот AppDomain ZB и вызвать некоторую операцию в ZB через Remoting.

Обратите внимание, что .NET Remoting имеет некоторые требования к классам, которые вы хотите использовать (наследование от MarshalByRef), а создание AppDomain - дорогостоящая операция.

Надеется, что это поможет

+0

«Вы можете иметь только одну версию сборки для AppDomain с» это не так. Можно даже ссылаться на две версии сборки из одной сборки, просмотреть дополнительную информацию о внешнем псевдониме, вот первое, что появляется в Google с помощью примера: http://blogs.msdn.com/ b/ansonh/archive/2006/09/28/extern-alias-walkthrough.aspx – Graham

+0

Использование двух приложений AppDomains является решением описанной проблемы. – Graham

+0

Вы правы, ответьте на обновления! –

0

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

Вам необходимо убедить среду выполнения загрузить ту же версию ZC для ZA и ZB. Я нашел два способа сделать это:

  1. Используйте элемент bindingRedirect в вашем файле App.config. Есть несколько деталей в this question.
  2. Используйте событие AppDomain.AssemblyResolve. Есть несколько деталей в this answer.

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

+1

Это не загрузка двух разных версий, это загрузка одной и той же версии дважды. –

+1

Когда я столкнулся с этой проблемой, @Cameron, время запуска загрузило версию 1.1 ZC при запуске ZA. Затем, когда я загрузил вставку ZB, время запуска загрузило версию 1.0 ZC с ней. Это то, что я имею в виду, загружая две разные версии. Чтобы ZA и ZB проходили объекты от ZC друг к другу, я должен был заставить их загружать одну и ту же версию ZC. Вот что я описываю, как это сделать в моем ответе. Я неправильно понял исходный вопрос? –

3
m_Assembly1 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "Old Version\Some.dll")) 
    m_Assembly2 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "New Version\Some.dll")) 

    Console.WriteLine("Old Version: " & m_Assembly1.GetName.Version.ToString) 
    Console.WriteLine("New Version: " & m_Assembly2.GetName.Version.ToString) 

    m_OldObject = m_Assembly1.CreateInstance("FullClassName") 
    m_NewObject = m_Assembly2.CreateInstance("FullClassName") 

Оттуда я использовал позднюю привязку и/или отражение для запуска моих тестов.

.NET: Load two version of the same DLL

+0

Отличный совет! не знал, что –

Смежные вопросы