Referenzieren von 2 verschiedenen Versionen von log4net in derselben Lösung

80

Ich verwende NHibernate 2.1.2.400, das auf log4net 1.2.10.0 verweist. Im selben Projekt verwende ich auch das SDK für die einfache Buchhaltung. Leider wird immer noch log4net 1.2.9.0 verwendet.

So kann ich NHibernate zum Laufen bringen, wenn ich auf log4net 1.2.10.0 verweise, aber das simplySDK nicht funktioniert. Und umgekehrt...

Ich vermute, die meisten Probleme sind darauf zurückzuführen, dass log4net seinen Assembly-Schlüssel geändert hat. Ich habe erfolglos versucht, eine Bindungsumleitung zu verwenden: Die beiden DLLs haben nicht denselben Schlüssel.

Ich denke darüber nach, NHibernate neu zu kompilieren, um log4net 1.2.9.0 zu verwenden, aber es scheint falsch zu sein, und ich habe das Gefühl, dass Simply Accounting das SDK nicht so schnell aktualisiert, um log4net 1.2.10.0 zu verwenden.

Was ist der beste Weg, um damit umzugehen? Ist es überhaupt möglich zu lösen?

Joel Gauvreau
quelle
2
Ich habe eine sehr ähnliche Frage unter stackoverflow.com/questions/1744543/…. Ich habe auf eine Neukompilierung zurückgegriffen. Ich denke, dies ist das Aufkommen von dll-hell v2.0.
Sandor Drieënhuizen
1
Beim Überprüfen Ihrer Frage habe ich stackoverflow.com/questions/2460542/2461746#2461746 gefunden , das mein Problem behoben hat.
Joel Gauvreau
Toll! Ich hatte mich gefragt, ob die CLR an verschiedenen Orten aussehen soll, und das hrefAttribut scheint den Trick zu tun. Vielen Dank für den Hinweis!
Sandor Drieënhuizen

Antworten:

149

Ich fand die Lösung, indem ich diese Antwort auf eine ähnliche Frage verwendete

Sie erstellen in Ihrem Projekt zwei Ordner, einen für jede Version von log4net. Platzieren Sie jede log4net.dll in ihrem entsprechenden Ordner, indem Sie die Datei zur Lösung hinzufügen (nicht mit Verweis hinzufügen). Sie können festlegen, dass die Eigenschaft "Kopie auf Ausgabeverzeichnis" immer kopiert wird, damit sie beim Erstellen automatisch in den Ausgabeordner kopiert wird.

Anschließend ändern Sie die Datei app.config, indem Sie Folgendes hinzufügen:

<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>

Sie können das Token für den öffentlichen Schlüssel einer Assembly mithilfe von sn -T [AssemblyName] abrufen.

Joel Gauvreau
quelle
2
Das scheint auch bei mir zu funktionieren. Ich habe log4net aus meiner Referenzliste für das Projekt entfernt, in dem der Konflikt aufgetreten ist. Da sich log4net.dll nicht in meinen Bin-Ordnern befindet, sahen meine href-Pfade eher wie ".. \ .. \ .. \ .. \ Lib \ NHibernate-2.0.1.GA \ log4net.dll" aus - nur a Relativer Pfad zu log4net auf dem Computer jedes Entwicklers mit unserem Build-System.
Jyoungdev
12
Ich bin mir nicht sicher, ob ich Folgendes verstehe: Wie erhalten Sie keine Kompilierungsfehler, wenn auf log4net nicht verwiesen wird?
Guidupuy
2
Dies ist fantastisch, es würde andere Fälle beheben, in denen eine einfache Bindungsumleitung aufgrund von API-Änderungen ebenfalls Probleme verursachen würde!
Rhys Bevilaqua
5
@guidupy Sie können auf das von Ihrem Code verwendete log4net verweisen, aber copyLocal in den Eigenschaften deaktivieren.
Jeff Martin
4
Für zukünftige Leser (ein Hinweis, den ich aus einer anderen Antwort gefunden habe, aber es ist ratsam, hier zu posten) ... für Webanwendungen (asp.net) hat die Referenz eine Optimierung: <codeBase version = "1.0.0.0" href = "bin \ folder \ namedll.dll "/>
granadaCoder
7

Sie können der Registrierung einen Ausschluss hinzufügen. Fügen Sie einfach diese Schlüssel hinzu:

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

Dadurch wird die .net-Laufzeitüberprüfung für die aufgelisteten Assemblys übersprungen. Theoretisch ist dies ein Sicherheitsproblem, aber da der private Schlüssel ohnehin offen ist, gibt es kaum Auswirkungen.

Joep Beusenberg
quelle
Wie Sie sagten, ist dies ein Sicherheitsproblem. Dies bedeutet auch, dass Sie diese Änderungen auf jeder Workstation vornehmen müssen, auf der die Software ausgeführt wird. In einem komplexen Unternehmensnetzwerk summieren sich solche Dinge zu einem großen Durcheinander. Ich möchte es lieber so weit wie möglich vermeiden. Die anderen Lösungen sind in sich geschlossen und portabel.
Joel Gauvreau
Wie gesagt, da die privaten Schlüssel sowieso öffentlich verfügbar sind, gibt es überhaupt kein wirkliches Sicherheitsproblem. Insbesondere in einem Unternehmensnetzwerk ist es einfacher, ein einzelnes Gruppenrichtlinienobjekt zu konfigurieren, als dies für jede verwendete LOB-Anwendung zu konfigurieren. Sie können es einmal auf Domänenebene konfigurieren und müssen nie wieder darüber nachdenken.
Joep Beusenberg
3

Wenn die Bindungsumleitung nicht funktioniert und das SDK für die einfache Abrechnung eine geschlossene Quelle ist, besteht eine mögliche Lösung darin, NHibernate neu zu kompilieren, um log4net 1.2.9.0 zu verwenden.

Diego Mijelshon
quelle
3
Das würde funktionieren, aber eine spezielle Version von nhibernate erstellen zu müssen, wäre auf der ganzen Linie schwieriger zu unterstützen ... danke.
Joel Gauvreau