Использование разных версий одной и той же сборки в одной папке
У меня следующая ситуация.
Проект A
- Uses Castle Windsor v2.2
- Uses Project B via WindsorContainer
Проект B
- Uses NHibernate
- Uses Castle Windsor v2.1
В папке bin проекта A у меня есть dll Castle.DynamicProxy2.dll v2.2 и NHibernate dll. Теперь проблема в том, что NHibernate зависит от Castle.DynamicProxy2.dll v2.1, которого нет. Как разрешить эту ситуацию.
Ответы
Ответ 1
Для решения проблемы я использовал следующую конфигурацию.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Castle.DynamicProxy2" publicKeyToken="407dd0808d44fbdc" />
<codeBase version="2.1.0.0" href="v2.1\Castle.DynamicProxy2.dll" />
<codeBase version="2.2.0.0" href="v2.2\Castle.DynamicProxy2.dll" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Castle.Core" publicKeyToken="407dd0808d44fbdc" />
<codeBase version="1.1.0.0" href="v2.1\Castle.Core.dll" />
<codeBase version="1.2.0.0" href="v2.2\Castle.Core.dll" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Ответ 2
Одним из решений (или обходным путем) было бы установить обе версии в Глобальном кэше сборки (GAC) на компьютере (-ах), на котором должно выполняться ваше программное обеспечение, и ссылаться на сборки, используя их сильные имена. Это предполагает, что сборки действительно имеют прочные имена.
Установка в GAC будет больно, если у вас будет несколько разработчиков или если вы планируете развернуть свое решение на многих компьютерах (например, в качестве приложения для конечного пользователя). В этом случае я полагаю (но, возможно, ошибаюсь), что ваш единственный вариант - объединить одну из двух версий в сборку, требующую этой версии. В вашем конкретном случае вам нужно Castle.DynamicProxy2.dll
v2.1 объединиться в NHibernate.dll
.
Вы можете использовать инструмент ILMerge для объединения сборок. Команда, которую вам нужно запустить, выглядит примерно так (непроверенная):
ILMerge /t:library /internalize /out:Deploy/NHibernate.dll
NHibernate.dll Castle.DynamicProxy2.dll
Коммутатор /internalize
сообщает ILMerge отмечать все типы из второй сборки (замок в этом случае) internal
в сборке вывода. Без этого вы можете получить ошибки компиляции при попытке скомпилировать проект, ссылающийся на ваш новый NHibernate.dll
и на полку версии Castle.DynamicProxy2.dll
v2.2, так как они будут содержать классы с одинаковыми именами.
Ответ 3
Одна вещь очень, очень, очень важная, что можно пропустить, если он не уделяет достаточного внимания.
Сборка, которую вы пишете в теге версии codeBase, должна быть сильной.
Из следующей ссылки: http://msdn.microsoft.com/en-us/library/efs781xb.aspx
Для сборок без сильного имени версия игнорируется, а загрузчик использует первое появление <codebase> внутри <dependentAssembly> . Если в приложении есть запись файл конфигурации, который перенаправляет привязку к другой сборке, перенаправление будет иметь приоритет, даже если версия сборки не будет соответствие запросу привязки.
Ответ 4
Я не думаю, что решение Hemanshu Bhojak является хорошим, так как вы не хотите загружать две версии одной и той же сборки в один и тот же контекст. В этой статье объясняется, почему:
http://msdn.microsoft.com/en-us/library/dd153782.aspx#avoid_loading_multiple_versions