Odwoływanie się do 2 różnych wersji log4net w tym samym rozwiązaniu

80

Używam NHibernate 2.1.2.400, który odwołuje się do log4net 1.2.10.0. W tym samym projekcie używam również prostego zestawu SDK do księgowania, niestety nadal używa on log4net 1.2.9.0.

Mogę więc uruchomić NHibernate, jeśli odwołam się do log4net 1.2.10.0, ale SimplySDK nie działa. I wzajemnie...

Domyślam się, że większość problemów wynika z faktu, że log4net zmienił swój klucz asemblera. Próbowałem użyć przekierowania powiązania bez powodzenia: 2 biblioteki DLL nie mają tego samego klucza.

Zastanawiam się nad przekompilowaniem NHibernate do korzystania z log4net 1.2.9.0, ale wydaje mi się, że to niewłaściwa rzecz i czuję, że Simply Accounting nie zaktualizuje swojego SDK do korzystania z log4net 1.2.10.0 w najbliższym czasie.

Jak najlepiej sobie z tym poradzić? Czy w ogóle można to rozwiązać?

Joel Gauvreau
źródło
2
Mam bardzo podobne pytanie pod adresem stackoverflow.com/questions/1744543/ ... Uciekłem się do ponownej kompilacji. Myślę, że to nadejście dll-hell v2.0.
Sandor Drieënhuizen
1
podczas sprawdzania twojego pytania znalazłem stackoverflow.com/questions/2460542/2461746#2461746, które rozwiązało mój problem.
Joel Gauvreau
Świetny! Zastanawiałem się nad tym, aby CLR wyglądał w różnych lokalizacjach i hrefwydaje się, że atrybut załatwia sprawę. Dziękuję za zwrócenie uwagi!
Sandor Drieënhuizen

Odpowiedzi:

149

Znalazłem rozwiązanie, używając tej odpowiedzi na podobne pytanie

Tworzysz 2 foldery w swoim projekcie, po jednym dla każdej wersji log4net. Umieść każdy plik log4net.dll w odpowiednim folderze, dodając plik do rozwiązania (nie z dodawaniem odwołania). Możesz ustawić właściwość copy to output directory na kopiowanie zawsze, tak aby była automatycznie kopiowana do folderu wyjściowego podczas kompilacji.

Następnie modyfikujesz plik app.config, dodając coś takiego:

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="log4net" publicKeyToken="681549d62126b7b8" />
        <codeBase version="1.2.9.0" href="log4netv1.2.9.0\log4net.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="log4net" publicKeyToken="1b44e1d426115821" />
        <codeBase version="1.2.10.0" href="log4netv1.2.10.0\log4net.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" />
        <codeBase version="1.2.11.0" href="log4net.dll" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

możesz uzyskać token klucza publicznego zestawu za pomocą sn -T [nazwa_zestawu]

Joel Gauvreau
źródło
2
Wydaje się, że to działa również dla mnie. Usunąłem log4net z mojej listy referencji dla projektu, w którym występował konflikt. Ponadto, ponieważ plik log4net.dll nie znajduje się w moich folderach bin, moje ścieżki href wyglądały bardziej jak „.. \ .. \ .. \ .. \ Lib \ NHibernate-2.0.1.GA \ log4net.dll” - po prostu względna ścieżka do miejsca, w którym log4net będzie się znajdować na komputerze każdego dewelopera z naszym systemem kompilacji.
jyoungdev
12
Nie jestem pewien, czy dostaję to: jak można uniknąć błędów kompilacji, jeśli nie ma odwołania do log4net?
guidupuy
2
To jest niesamowite, naprawiłoby inne przypadki, w których proste przekierowanie wiązania mogłoby zepsuć wszystko z powodu zmian w API!
Rhys Bevilaqua
5
@guidupy możesz odwołać się do log4net, którego używa twój kod, ale wyłącz copyLocal we właściwościach.
Jeff Martin
4
dla przyszłych czytelników (wskazówka, którą znalazłem w innej odpowiedzi, ale rozsądnie zamieścić ją tutaj) ... w przypadku aplikacji internetowych (asp.net) odniesienie ma poprawkę: <codeBase version = "1.0.0.0" href = "bin \ folder \ namedll.dll "/>
granadaCoder,
7

Możesz dodać wykluczenie do rejestru. Po prostu dodaj te klucze:

HKEY_LOCAL_MACHINE\Software\Microsoft\StrongName\Verification\log4net,681549d62126b7b8
HKEY_LOCAL_MACHINE\Software\Microsoft\StrongName\Verification\log4net,1b44e1d426115821
HKEY_LOCAL_MACHINE\Software\Microsoft\StrongName\Verification\log4net,669e0ddf0bb1aa2a

Spowoduje to pominięcie sprawdzania poprawności przez środowisko uruchomieniowe .NET dla wymienionych zestawów. W teorii jest to kwestia bezpieczeństwa, ale ponieważ klucz prywatny i tak jest otwarty, nie ma prawie żadnego wpływu.

Joep Beusenberg
źródło
Jak powiedziałeś, jest to kwestia bezpieczeństwa. Ponadto oznacza to, że musisz wprowadzić te zmiany na każdej stacji roboczej, na której działa oprogramowanie. W złożonej sieci przedsiębiorstwa takie rzeczy sumują się, tworząc ogromny bałagan. Wolałbym tego unikać tak bardzo, jak to tylko możliwe. Pozostałe rozwiązania są samodzielne i przenośne.
Joel Gauvreau
Jak powiedziałem, ponieważ klucze prywatne i tak są publicznie dostępne, nie ma żadnego prawdziwego problemu z bezpieczeństwem. Zwłaszcza w sieci korporacyjnej łatwiej byłoby skonfigurować pojedynczy obiekt zasad grupy, niż skonfigurować go dla każdej używanej aplikacji LOB. Możesz to skonfigurować raz na poziomie domeny i nigdy więcej o tym nie myśleć.
Joep Beusenberg
3

Jeśli przekierowanie powiązań nie działa, a prosty księgowy SDK jest zamkniętym źródłem, możliwym rozwiązaniem jest ponowna kompilacja NHibernate, aby używał log4net 1.2.9.0.

Diego Mijelshon
źródło
3
To by działało, ale konieczność zbudowania specjalnej wersji nhibernate byłaby trudniejsza do utrzymania w przyszłości… dzięki.
Joel Gauvreau