2012-07-04 9 views
9

Co to jest najlepsza praktyka w świecie .NET do zarządzania przechodnimi zależnościami powodującymi konflikt wersji?Zależność przejściowa powodująca konflikt Wersję tego samego pliku DLL

szczegółowo: Projekt A zależy od projektu B, który z kolei zależy od biblioteki C

również

Projekt A zależy również od projektu X, która zależy od różnych i (potencjalnie) niezgodnej wersji biblioteki C

A-> B-> Cv1.0
&
A-> X> Cv2.0
gdzie
CV1 .0 <> Cv2.0

  • Czy istnieje sposób, aby to zadziałało?

  • Czy można to zrobić BEZ korzystania z GAC?

  • Czy można to zrobić, nawet jeśli B i X są tylko w formacie binarnym (źródło niedostępne)?

Innymi słowy, istnieje sposób, w którym każdy z projektów B i X może korzystać z własnych zależności, jeśli są używane razem w Projekcie A, nie powodując konfliktów.

UWAGA: Rozumiem, że w idealnej sytuacji nie powinienem mieć tego problemu w ogóle, ale w miarę rozszerzania się zewnętrznych bibliotek, będzie to nieunikniony efekt uboczny. Zastanawiam się więc, czy powinien się pojawić jak najlepiej sobie z tym poradzić.

+1

Idealnie powinieneś odbudować lub zaktualizować B tak, aby zależało to od aktualnej wersji C. Jeśli nie możesz tego zrobić, możesz spróbować ponownie mapować wersje. http://stackoverflow.com/a/11126867/48082 Nie gwarantuje to działania! – Cheeso

+1

Uzgodniono, że najlepiej oczyścić swoje projekty, aby uniknąć sytuacji na miejscu, ale nie zawsze jest to możliwe, stąd pytanie. – Newtopian

+0

remapping DLL w jakiś sposób jest dobry tylko wtedy, gdy obie wersje są kompatybilne ze sobą. Najgorszy scenariusz polega na tym, że w przypadku, gdy nie są kompatybilne, istnieje sposób, aby każda średnia zależność korzystała z wersji, dla której została stworzona i nadal wykonuje pracę, której oczekuje od niej główny projekt. – Newtopian

Odpowiedz

4

Istnieje wiele podobnych pytań dotyczących przepełnienia stosu. Dla np. Referencing 2 different versions of log4net in the same solution

Podsumowanie:

  1. Sprawdź, czy wdrożyć montażowej C w folderach 1.0 i 2.0, odpowiednio w folderze zawierającym główny plik wykonywalny.
  2. Zmień plik app.config i to coś jak następujące:
<configuration> 
    <runtime> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <dependentAssembly> 
     <assemblyIdentity name="C" publicKeyToken="C's public key token" /> 
     <codeBase version="version string for C1.0 e.g. 1.0.0.0" href="1.0\C.dll" /> 
     <codeBase version="version string for C2.0 e.g. 2.0.0.0" href="2.0\C.dll" /> 
     </assemblyIdentity> 
     </dependentAssembly> 
    </assemblyBinding> 
    </runtime> 
</configuration> 

można uzyskać tokenu klucza publicznego C przy sn -T C.dll

Jeśli v1. 0 i v2.0 C mają inny klucz publiczny (choć najlepiej nie powinny), a następnie zawierają dwa znaczniki dependentAssembly.

+1

jest rzeczywiście wiele pytań, ale nikt nie odpowiedział na moje pytanie. Moje rozumienie assemblyBinding było to, że pozwala określić, która biblioteka DLL jest używana, dla którego przestrzeni nazw i odpowiednio przekierować połączenia. Tutaj każda ścieżka wywołania docelowo będzie kierować pojedynczą bibliotekę DLL. W przedstawionym scenariuszu mamy dwie identyczne ścieżki wywołania, które muszą być skierowane na dwie różne biblioteki DLL. Jedyną różnicą jest to, że każdy jest wywoływany z innej "macierzystej" biblioteki DLL. Tak jest, chyba że nie zrozumiałem poprawnie celu assemblyBinding. – Newtopian

+0

Tha powiedział, że myślę, że jeśli wydawca dwóch zależności (B i X w powyższym przykładzie) miał specjalnie hardwire, to zależność od wersji DLL (C powyżej) podczas tworzenia ich bibliotek wszystko działało (pod warunkiem, że zarówno C Dll są jednoznacznie identyfikowalne pliki, tzn. inne nazwy i/lub ścieżki). Będę musiał poeksperymentować nieco z assemblyBinding, zobacz, co można zrobić – Newtopian

+0

Jeśli C jest silnie nazwane, powyższe powinno działać i powinno być możliwe ładowanie poprawnej wersji C dla B i X. Jeśli nie ma silnej nazwy, ale wciąż ma wersję (jak określono za pomocą atrybutu AssemblyVersion), możesz poeksperymentować z usunięciem klucza publicKey i sprawdzić, czy nadal działa. Jeśli to nie zadziała, myślę, że jedyną nadzieją będzie wydarzenie AssemblyResolve. Postaram się sprawdzić wszystkie te ifs i buts i podzielić się wynikami. –