Использование нескольких версий одной и той же библиотеки DLL
Мне было поручено создать новый модуль для приложения, и поэтому я добавляю в проект новые библиотеки DLL. Все хорошо и хорошо.
Однако в моих DLL я бы хотел использовать новую версию внешней DLL (над которой я не контролирую). Если я просто ссылаюсь на новую DLL и работаю только с этим, мой код будет работать, но старый код перестанет работать.
Could not load file or assembly 'itextsharp, Version=5.0.6.0, Culture=neutral, PublicKeyToken=8354ae6d2174ddca' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Я пробовал простой трюк по изменению имени DLL, но это, по-видимому, было слишком наивным для меня, чтобы думать, что это сработает. Я пробовал использовать внешние псевдонимы (определяя их в своих ссылках), но я до сих пор не знаю, как получить два файла с тем же именем в одной папке BIN …
- Как добавить ссылку программно
- Странное поведение const_cast
- В терминах laymans, что означает «статический» в Java?
- Почему ссылка, не связанная с константой, не может привязываться к временному объекту?
- c # Visual Studio ... добавление ссылок программно
Что мне делать?
- Разница между указателем и ссылкой как параметр streamа
- Можно ли ссылаться на переменную со строкой и int?
- Что лучше, возвращаемое значение или параметр out?
- В чем разница между ключевыми словами «ref» и «out»?
- Какое время жизни я использую для создания структур Rust, которые циклически ссылаются друг на друга?
- Каковы различия между переменной указателя и ссылочной переменной в C ++?
- Насколько велика ссылка на объект в .NET?
- Ссылка на dll не может быть добавлена
Вы можете загрузить другую версию в конкретный AppDomain
Возможно, слишком подробно, но вот статья, демонстрирующая использование AppDomains в полезной настройке и как они работают:
http://msdn.microsoft.com/en-us/magazine/cc164072.aspx
В самом основном смысле это сводится к этому образцу кода:
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); ... static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { if (/*some condition*/) return Assembly.LoadFrom("DifferentDllFolder\\differentVersion.dll"); else return Assembly.LoadFrom(""); }
Другим жизнеспособным вариантом является использование extern
, как описано здесь:
http://blogs.msdn.com/b/abhinaba/archive/2005/11/30/498278.aspx
Предположим, что у вас есть структура проекта следующим образом:
… где A
и B
– библиотеки classов, а C
– проект исполняемого типа (например, единичный тест или консольный проект).
Предположим, что структура папок такова:
ABC.sln A/A.csproj A/... B/B.csproj B/... C/C.csproj C/... lib/thirdparty4/thirdparty.dll lib/thirdparty5/thirdparty.dll
Если бы мы попытались наивно ссылаться на наши проекты вместе, у нас возникла бы проблема: две версии thirdparty.dll
будут скопированы в одну и ту же папку (каталог вывода (т. thirdparty.dll
) C
). Нам нужен способ, чтобы C
копировал обе библиотеки dll в свой выходной каталог и предоставлял механизм для ссылки на один.
Чтобы решить эту проблему, я модифицировал C.csproj
чтобы содержать следующее:
PreserveNewest thirdparty4\thirdparty.dll PreserveNewest thirdparty5\thirdparty.dll
Это даст указание создать в своем выходном каталоге как thirdparty4\thirdparty.dll
и thirdparty5\thirdparty.dll
.
Теперь, после построения C
, его выходной каталог выглядит следующим образом:
C\bin\Debug\A.dll C\bin\Debug\B.dll C\bin\Debug\C.dll C\bin\Debug\thirdparty4\thirdparty.dll C\bin\Debug\thirdparty5\thirdparty.dll
Чтобы указать C
для использования обеих этих библиотек, я добавил к нему файл App.config
со следующим:
Это даст указание сборке, в зависимости от того, какая версия нужна, использовать одну DLL или другую, которые будут доступны в подпапках выходного каталога. (Элементы bindingRedirect не являются обязательными, но вы можете использовать их, если вам нужен ряд изменений для этого.)
Вы также можете полагаться на redirect привязки сборки для своей сильной именованной сборки, как описано в http://msdn.microsoft.com/en-us/library/2fc472t2.aspx .
У вас будет только одна версия файла (последняя), и обе ссылки разрешат ее.
Если решение AppDomains не применимо в вашем случае, вы находитесь под давлением времени, имеете противоречивые требования (как это когда-либо случается) и не возражаете против смехотворно выдуманных хаков:
- Декомпилируйте новую версию сборки, используя инструмент ildasm (часть командной строки Developer, включенная в Visual Studio)
- Отредактируйте сгенерированный файл .il, чтобы найти / заменить ссылки пространства имен сборки. Используя приведенный пример, это будет изменение от itextsharp.X до itextsharp.new.X
- Аналогичным образом отредактируйте значение для атрибута AssemblyTitleAttribute. Это требует перевода символов ASCII в шестнадцатеричный.
- Перекомпилируйте файл .il с помощью ilasm
- Обратите внимание, что это может потребоваться повторить для любых зависимых сборок (например, someassembly.core.whatever)
- Добавьте новые DLL-файлы в свой проект с другим именем и укажите их явно (а не через nuget или что-то еще)
Эй, не смотри на меня так. Я действительно сказал смешно надуманный взлом …