17

Newtonsoft.Json wydania niekompatybilne wersje o tej samej nazwie silne, tylko zmiana wersji pliku.Newtonsoft Json.NET niekompatybilność wersji (DLL piekło)

Według MSDN:

zespołów, które mają ten sam silny nazwa powinna być identyczna.

Z tego powodu nasze przerwy aplikacyjne jeśli inna aplikacja, poza naszą kontrolą, stawia inną wersję Newtonsoft.Json.dll do GAC

jest jakiś sposób, aby wymusić .NET załadować określoną wersję my potrzeba?

Aktualizacja:

Pozwól mi wyjaśnić problem, bardziej w głębi.

W .NET, o ile mi wiadomo, nie ma mechanizmu do rozwiązywania złożeń, zanim CLR spróbuje je rozwiązać i nie powiedzie się.

Występuje tylko zdarzenie AppDomain.AssemblyResolve i jest uruchamiane tylko wtedy, gdy montaż nie został rozwiązany. Zwykle to wystarczy.

Jednak w przypadku Newtonsoft.Json nie uda się rozwiązać zestawu po prostu załaduje nieprawidłowy.

Dzieje się tak, ponieważ Newtonsoft.Json wydaje niekompatybilne wersje o tej samej nazwie.

przykład:

Umożliwia powiedzieć, że nasze zgłoszenie skompilowane NJdll (wersja zespołu 1,0, plik wersja 1,0)

Następnie innej aplikacji, umieścić drugą wersję tego samego niezgodną dll się do GAC NJdll (montaż wersja 1,0 wersji pliku 1,1)

B Ponieważ zmieniają tylko wersję pliku i nie zmieniają wersji zespołu, te dwa zestawy mają taką samą silną nazwę.

Tak więc dla naszej aplikacji .NET próbującej rozwiązać N.J.dll (wersja montażowa 1.0), zobaczy dll w GAC i załaduje ją. (Ponieważ .NET zawsze preferuje montaż z GAC do montażu z folderu "bin")

Ale załadowany zespół jest niewłaściwy. Ma wersję 1.1 pliku i nie jest kompatybilny z wersją 1.0.

Ponieważ oba zespoły mają tę samą wersję zespołu, system .NET nie widzi między nimi żadnej różnicy. Ale wtedy, gdy faktycznie spróbujesz rozwiązać jakąś klasę lub członka wewnątrz, nie powiedzie się, ponieważ została zmieniona w wersji 1.1.

Cała aplikacja kończy się niepowodzeniem z nieprzewidywalnymi błędami.

Moje pytanie brzmi: czy mogę wcześniej sprawdzić, jak prawidłowo korygować pierwszy zespół.NET załadować niewłaściwy?

Aktualizacja

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

problemy z tym problemem był zamknięty z komentarzem, które pokazują, że autor nie rozumie Newtonsoft.Json wersjonowanie .NET i dlaczego jest to ważne.

+2

Stało się to nawet z Microsoft przed - J # został ponownie wydany z wersją montaż niezmienioną. Jeśli wykryjesz to podczas instalacji, możesz poprosić użytkownika o zainstalowanie odpowiedniej wersji zespołu w GAC. Inną opcją jest stworzenie własnego pliku binarnego z tych samych źródeł i przypisanie jej silnej nazwy, jeśli chcesz (jeśli licencja na to pozwala). – IgorK

+1

Problem jest jeszcze większy. Sam Microsoft używa Newtonsoft Json.NET w swoich bibliotekach i pakietach SDK. Więc wszystko, co ich używa, mogło w każdej chwili przerwać z bardzo dziwnymi błędami. –

+1

To w końcu wyjaśnia kilka nieoczekiwanych wyjątków, które otrzymałem w aplikacji interfejsu API MVC pół roku temu. Aplikacja korzystała z Json.Net w wyższej wersji niż wersja w pakiecie z samym WebAPI. Aplikacja działała poprawnie natychmiast po wdrożeniu, dopóki IIS nie zdecyduje się jej zawiesić (po około 30 minutach braku użycia). Gdy ktoś uzyskuje dostęp do aplikacji po zawieszeniu, IIS próbuje go ponownie uruchomić, ale w jakiś sposób zabrania wersji Json.Net i moja działająca aplikacja zmarła notorycznie. Nie miałem Json.Net w GAC, korzystałem tylko z NuGet do zarządzania moimi zależnościami. –

Odpowiedz

3

Moduł ładujący złożenia będzie sprawdzać tylko w poszukiwaniu brakujących złożeń, tj. Zespołów, które nie zostały jeszcze załadowane. Jeśli wdrożysz bibliotekę DLL do folderu instalacji aplikacji, a następnie załaduj ją jawnie po uruchomieniu aplikacji, wówczas program ładujący zespołu nie spróbuje ponownie załadować go z GAC.

Możesz załadować zespół jawnie, używając metody Assembly.LoadFrom.

Aby uzyskać więcej informacji, patrz https://msdn.microsoft.com/en-us/library/dd153782(v=vs.110).aspx.

+0

Tak, ale jest to bardzo trudne do osiągnięcia. Ponieważ musi się zdarzyć, zanim zostanie zainicjowany dowolny typ, który używa danego zestawu. Musi być bardzo wcześnie i nie znam żadnego zdarzenia ani punktu wejścia, który niezawodnie stanie się tak wczesnym –

+0

Jakiego rodzaju jest to aplikacja? Czy to jest strona internetowa, aplikacja konsolowa ... Prawie zawsze jest miejsce startowe, gdzie można umieścić ten kod, ale gdzie dokładnie zależy od rodzaju aplikacji. – bikeman868

+1

Można również utworzyć aplikację ładującą. Aplikacja ładująca utworzy nową domenę aplikacji, jawnie załaduje biblioteki DLL dla aplikacji do nowej domeny aplikacji, zanim wywoła punkt wejścia aplikacji, aby go uruchomić. To najbardziej ekstremalne rozwiązanie, jakie mogę sobie wyobrazić i prawie na pewno nie jest to konieczne w twojej sytuacji. – bikeman868