Номера версий сборок, подписанные сборки Почему я получаю FileLoadExceptions
Моя проблема:
У меня есть подписанная сборка A.dll, которая имеет версию 1.0.0.0. У меня есть другая сборка (скажем, B.dll), которая ссылается на A.dll.
После того, как обе сборки обе сборки загружаются нормально без каких-либо проблем. Теперь, если версия A.dll изменяется на 1.0.0.1 и перекомпилируется, нужно ли перекомпилировать B.dll?
Я спрашиваю, потому что у меня есть этот точный сценарий, где после того, как A.dll изменили его версию, я теперь получаю следующее исключение при попытке загрузить B.dll:
Unhandled Exception: System.IO.FileLoadException:
Could not load file or assembly A, Version=1.0.0.0,
Culture=neutral, PublicKeyToken…
Это заставляет меня думать, что ответ на этот вопрос всегда да. Однако у меня есть другой пример, где у меня есть две сборки, которые имеют точный сценарий, описанный выше, и у меня нет проблем с загрузкой сборок.
Какой сценарий / условия вызывают это исключение? Если кто-то может предложить какое-то понимание этого, это будет с благодарностью. Благодарю.
2 ответа
Когда сборка строго названа, все, что ссылается на нее, будет искать эту конкретную версию.
Вы правы, что "Конкретная версия" в Visual Studio никак не влияет на время выполнения. Фактически, "Конкретная версия" в основном означает "Когда вы запускаете сборку, если MSBUILD не может найти версию, на которую ссылалась, произойдет сбой сборки или просто использовать следующую версию, которая может быть найдена в файловой системе?"
Если вы перекомпилируете A и развернете его как частичное обновление (вместо того, чтобы полностью развернуть приложение), то, если в приложении есть что-то, ссылающееся на старую версию, ваше приложение может сломаться, если у вас все еще не установлена старая версия A также доступен (т.е. вы не перезаписали его).
Это основная причина, по которой некоторые продукты используют GAC, потому что он может хранить несколько версий одной и той же DLL без перезаписи друг друга - если вы пытались развернуть разные версии одного и того же файла в папке bin (при условии, что у них было одинаковое имя файла) что они обычно и делают), они будут перезаписывать друг друга, и вы получите только одну из DLL в вашем продукте!
Еще один трюк, который вы можете сделать, - это поместить ваши "обновленные" библиотеки DLL в подпапку в двоичном каталоге и отредактировать файл app.config, чтобы сообщить среде выполнения, где их искать. http://support.microsoft.com/kb/837908
Таким образом, чтобы подвести итог, сборка со строгим именем использует больше, чем просто имя, чтобы определить идентичность сборки - изменение ее версии можно рассматривать как полное изменение ее имени.
Независимо от того, подписана ли сборка А, не обязательно. Скомпилировали ли вы "Specific Version = true" в ссылке на сборку проекта B для A? Если это так, то CLR будет использовать строгие правила, чтобы определить, является ли данная версия A приемлемой. Если нет, то CLR будет использовать менее строгие правила, и вам не нужно будет перекомпилировать, если A увеличивает свою версию.
В зависимости от вашей среды вы можете не беспокоиться о том, что A нарушит совместимость в будущей версии. Если это вас не беспокоит, вам следует изменить ссылки на сборку на "Specific Version = false". (На работе у нас есть обе ситуации: например, когда мы зависим от стороннего элемента управления, мы обычно устанавливаем "Specific Version = true", но когда мы потребляем внутренний компонент общего доступа, который мы будем тестировать на соответствие приложения, которые его используют, мы удостоверимся, что "Specific Version = false", поэтому нам не нужно перекомпилировать.)
Вы можете найти дополнительную информацию, в том числе о том, как обойти это с помощью файлов конфигурации, когда вам нужно скомпилировать с определенной версией, но вы хотите перенаправить привязки позже, в MSDN: Перенаправление версий сборки
Надеюсь, это поможет!