17

Newtonsoft.Json выпускает несовместимые версии с таким же сильным именем, только изменяя версию файла.Newtonsoft Json.NET версия несовместимости (DLL ад)

По MSDN:

Агрегаты, которые имеют такое же сильное имя должно быть одинаковым.

Из-за этого наши перерывы приложения, если другое приложение, вне нашего контроля, ставит другую версию Newtonsoft.Json.dll в GAC

Есть ли способ заставить .NET загрузить определенную версию мы необходимость?

Update:

Позвольте мне объяснить проблему более подробно.

В .NET, насколько я знаю, нет механизма для решения сборок до того, как CLR попытается их разрешить и сбой.

Существует только событие AppDomain.AssemblyResolve, и оно срабатывает только тогда, когда сборка не решена. Обычно этого достаточно.

Но в случае с Newtonsoft.Json он не может решить проблему сборки, он просто загружает неправильный.

Это происходит потому, что Newtonsoft.Json выпускает несовместимые версии с таким же сильным именем.

Пример:

Допустим, наше приложение компилируется против NJdll (версия сборки 1,0, версия файла 1,0)

Тогда некоторые другие приложения, поставить другие несовместимые версии той же библиотеки DLL в к ГАУ NJdll (версия сборки 1.0, версия файла 1,1)

Б ecause они только изменяют версию файла и не изменяют версию сборки, эти две сборки имеют такое же сильное имя.

Итак, для нашего приложения .NET, пытающегося разрешить N.J.dll (сборка версии 1.0), он видит dll в GAC и загружает его. (Потому что .NET всегда предпочитает сборку из GAC для сборки из папки «bin»)

Но сборка, загруженная неправильно. Он имеет версию файла 1.1 и не совместим с версией 1.0.

Поскольку обе сборки имеют одинаковую версию сборки, .NET не видит различий между ними. Но тогда, когда он действительно пытается решить какой-то класс или член внутри, он терпит неудачу, потому что он был изменен в версии 1.1.

И все приложение не работает с непредсказуемыми ошибками.

Итак, мой вопрос: могу ли я как-то правильно загрузить сборку сначала.Неверная загрузка NET?

Update

https://github.com/JamesNK/Newtonsoft.Json/issues/615 https://github.com/JamesNK/Newtonsoft.Json/issues/1001

Проблемы с этой проблемой был закрыт с комментариями, которые показывают, что автор Newtonsoft.Json не понимают .NET версий и почему это важно.

+2

Это случилось даже с Microsoft, прежде чем - J # была повторно выпущена с версией сборки без изменений. Если вы обнаружите его во время установки, вы можете попросить пользователя установить надлежащую версию сборки в GAC. Другой вариант - создать собственный бинарный файл из тех же источников и присвоить ему сильное имя по вашему желанию (если лицензия разрешена) – IgorK

+1

Проблема еще больше. Microsoft сама использует Newtonsoft Json.NET в своих библиотеках и SDK. Так что все, что их использует, может сломаться в любое время с очень странными ошибками. –

+1

Это, наконец, объясняет кучу неожиданных исключений, которые я получил в приложении веб-API MVC полгода назад. Приложение использовало Json.Net с более высокой версией, чем версия, связанная с самим WebAPI. Приложение сразу после развертывания прекратило работу, пока IIS не решит приостановить его (примерно через 30 минут без использования). Когда кто-то обращается к приложению после приостановки, IIS пытается запустить его снова, но как-то испортил версию Json.Net, и мое рабочее приложение скончалось. У меня не было Json.Net в GAC, я использовал NuGet для управления моими зависимостями. –

ответ

3

Сборочный погрузчик будет только проверять отсутствие сборок, то есть сборок, которые еще не загружены. Если вы разворачиваете DLL в папку установки приложения, то загружайте ее явно при запуске приложения, после чего загрузчик сборок не будет пытаться загрузить его снова из GAC.

Вы можете загрузить сборку явно, используя метод Assembly.LoadFrom.

Для получения дополнительной информации см. https://msdn.microsoft.com/en-us/library/dd153782(v=vs.110).aspx.

+0

Да, но это очень сложно. Поскольку это должно произойти до того, как будет инициализирован любой тип, который использует данную сборку. Это должно быть очень рано, и я не знаю какого-либо события или точки входа, который надежно случается так рано –

+0

Какое приложение? Это веб-сайт, консольное приложение ... Почти всегда есть место для запуска, где вы можете поместить этот код, но где точно зависит от типа приложения. – bikeman868

+1

Вы также можете создать приложение-загрузчик. Приложение-загрузчик создаст новый домен приложения, явно загрузит dll для вашего приложения в новый домен приложения, прежде чем вызывать точку входа вашего приложения для его запуска. Это самое экстремальное решение, которое я могу себе представить, и это почти наверняка не обязательно для вашей ситуации. – bikeman868