Почему для этого проекта требуется перенаправление привязки сборки? - PullRequest
0 голосов
/ 10 апреля 2019

Я использовал https://icanhasdot.net для анализа зависимостей NuGet примера проекта, с которым я экспериментировал.Вот результаты: enter image description here

На графике не показаны конкретные версии, но я нацеливаюсь на .NET Framework 4.5 для проекта и на основе представления «Управление Nuget»в Visual Studio я знаю, что все пакеты NuGet (т.е. все зеленые квадраты на графике) в моем проекте требуют Newtonsoft.Json > = 6.0.8, например:

enter image description here

Я хочу использовать немного более новую версию Newtonsoft.Json для своего проекта, поэтому я добавил версию 8.0.2.Поскольку это определенно> = 6.0.8, я бы не ожидал, что это вызовет проблемы.Однако, когда я запускаю программу, я немедленно получаю исключение System.IO, сообщающее, что что-то не найдено в Newtonsoft.Json 6.

Я исправил эту проблему, добавив файл app.config с перенаправлением привязки сборки( Перенаправление привязки сборки: как и почему? ) к более новой версии Newtonsoft.Json, и это устранило проблему.Однако я не понимаю, почему такая привязка необходима, если все пакеты NuGet, от которых зависит мой проект, требуют require> = 6.0.8, что определенно является 8.0.2.

1 Ответ

2 голосов
/ 10 апреля 2019

В среде выполнения .NET существует концепция, называемая сильным именованием.

Возможно, я неправильно получаю много технических деталей, но в основном сборка, имя которой не имеет строгого имени, говорит: "Меня зовут zivkan.utilities.dll"и когда другая сборка компилируется с моей сборкой, ссылка говорит: «Мне нужен класс с именем zivkan.utilities.thing из zivkan.utilities.dll».Таким образом, он ничего не знает о версиях, и вы можете добавить любой zivkan.utilities.dll, который содержит класс zivkan.utlities.thing, и среда выполнения попытается его запустить.

Если я подписан со строгим именем zivkan.utilities.dll, то теперь он собираетсяобъявляет себя как «меня зовут zivkan.utilites.dll версия 1.0.0 с открытым ключом ...» (я собираюсь пропустить часть открытого ключа для остальной части моего ответа).Теперь, когда против него скомпилирована другая сборка, скомпилированная ссылка говорит: «Мне нужна zivkan.utilities.dll версия 1.0.0».Теперь, когда это выполняется, среда выполнения .NET загружает только zivkan.utilities.dll версию 1.0.0 и завершается ошибкой, если версия отличается, как вы видели, вы получаете ошибку.У программы могут быть перенаправления привязки, чтобы сообщить загрузчику сборки среды выполнения .NET, что при обнаружении запроса на zivkan.utilties между версиями 0.0.0.0 и 2.0.0.0 использовать версию 2.0.0.0, как вы решили свою проблему.

Версии NuGet и версии сборки - это две разные концепции, но, поскольку они, как правило, имеют одно и то же значение (или очень похожее значение), это не слишком известное различие.Версии сборок выполняются во время выполнения, а версии пакетов NuGet - во время сборки.

Итак, представьте себе ситуацию без перенаправлений привязки.Ваша программа CommandLineKeyVaultClient загружена и зависит от Newtonsoft.Json версии 8.0.2..NET Runtime загружает Newtonsoft.Json.dll и подтверждает, что это действительно версия 8.0.2.Затем среда выполнения .NET видит, что CommandLineKeyVaultClient также имеет зависимость от Microsoft.Rest.ClientRuntime.dll, скажем, версии 1.0.0.0.Итак, среда выполнения .NET загружает эту dll и подтверждает номер версии сборки.Microsoft.Rest.ClientRuntime.dll зависит от Newtonsoft.Json.dll версии 6.0.8.Среда выполнения .NET видит, что Newtonsoft.Json версия 8.0.2 уже загружена, но версия не совпадает и перенаправление привязки отсутствует, поэтому давайте попробуем загрузить Newtonsoft.Json.dll на диск (на самом деле есть ловушка, которую вы можете использовать, чтобы сообщитьзагрузчик для загрузки DLL из другого каталога, когда вам действительно нужно загрузить разные версии одной и той же сборки, вы можете).Когда он пытается, он видит, что версия сборки не совпадает со строгой именованной зависимостью, и терпит неудачу, говоря «не может загрузить Newtonsoft.Json.dll версия 6.0.8», что верно, потому что версия на диске на самом деле 8.0.2.

Если вы используете пакеты NuGet с использованием PackageReference, NuGet будет смотреть не только на транзитивные зависимости NuGet, но также на зависимости проекта и строить график всех необходимых сборок (проекта или nuget).Затем MSBuild должен автоматически определить, когда две разные сборки зависят от разных версий одного и того же имени сборки, и сгенерировать перенаправления привязки.Следовательно, при использовании PackageReference это обычно не должно быть проблемой.

Однако, если вы используете packages.config для определения ваших зависимостей NuGet, NuGet попытается добавить перенаправления привязки, когда обнаружит конфликт версий (который ядумаю, что вы можете отказаться от).Но так как это рассчитывается в тот момент, когда вы модифицируете зависимости NuGet в этом проекте (установите, обновите или удалите пакет), возможно получить перенаправления привязки несинхронно, и есть проблема с зависимостями проекта в проект и тем, что NuGet упаковывает в них.ссылки на проекты используют.

В любом случае, я надеюсь, это объясняет, почему вы получаете ошибку загрузки dll, когда все ваши проекты имеют зависимость NuGet> = 6.0.8.Я еще раз повторяю, что версии сборок и версии NuGet - это разные вещи, даже если они имеют одинаковое значение, а среда выполнения .NET позволяет загружать разные версии одной и той же сборки одновременно и требует инструкций, когда вы этого не хотите., что такое перенаправления привязки.

...