Seltsames Verhalten beim Mischen Beladung von Baugruppen mittels Assembly.LoadFrom und Assembly.Load
-
03-07-2019 - |
Frage
Schräge Verhalten beim Laden von Baugruppen Mischen mit Assembly.LoadFrom und Assembly.Load
Ich habe ein seltsames Verhalten auf, wenn Baugruppen mit Assembly.LoadFrom und später mit Assembly.Load Laden.
Ich lade eine Baugruppe mit Assembly.LoadFrom, wo die Montage in einem Ordner befindet, der nicht der Ausführung Ordner ist.
Später in meinem Test-Code, wenn ich versuche, mit Assembly.Load diese Versammlung noch einmal zu laden, schlägt die Last mit einem System.IO.FileNotFoundException ( „Kann nicht Datei oder Assembly geladen werden ...“) trotz der Tatsache, dass die Baugruppe ist bereits geladen. Die Last versagt sowohl mit dem starken Namen und dem nicht-starken Namen (der ursprüngliche Grund für das Laden wieder diese Anordnung eine Verwendung eines BinaryFormatter ist).
Für den Fall jedoch wird die Anordnung in der Ausführung Ordner die spätere Belastung in beiden Fällen gelingt gelegen, mit dem starken Namen und dem nicht-starken Namen. In diesem Fall können Sie sehen, dass zwei identische Baugruppen aus zwei verschiedenen Orten geladen werden.
Ein einfaches Codebeispiel, das dieses Problem erschafft -
Montage Assembly1 = Assembly.LoadFrom (@ "C: \ a.dll");
// Laden mit starkem Namen nicht Montage assembly2 = Assembly.Load (@ "ein, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = 14986c3f172d1c2c ");
// Laden auch mit einem nicht stark ausfällt Montage assembly3 = Assembly.Load (@ "a");
- Jede Erklärung, warum die CLR die bereits geladene Assembly ignoriert?
- Jede Idee, wie kann ich dieses Problem lindern?
Danke.
Lösung
Das ist nicht komisch. Gemäß der Dokumentation, wird mit Laden und Loadfrom Laden legen Sie die Baugruppen in unterschiedlichen Kontexten. Diese helfen könnte.
- Jede Erklärung, warum die CLR die bereits geladene Assembly ignoriert?
Weil sie in einem anderen Kontext sind.
- Jede Idee, wie kann ich dieses Problem lindern?
Laden aus dem gleichen Kontext, oder helfen, die CLR die Versammlung zu finden, vielleicht durch einen Handler AppDomain.AssemblyResolve
anbringen.
Alternative
Wenn der Standort Sie Baugruppen aus laden ist ein Unterordner unter AppDomain.BaseDirectory Sie einfach einen Eintrag in Ihrem App.config hinzufügen:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;bin2\subbin;bin3"/>
</assemblyBinding>
</runtime>
</configuration>
Andere Tipps
@Kent Boogart: Das scheint die richtige Erklärung. Für eine vollständige Erklärung, Suzanne Cook hat dieses Blog-Post, die ein wenig mehr als das Original ausarbeitet Sie auf dem Laufenden: http://blogs.msdn.com/suzcook/archive/2003 /05/29/57143.aspx
Im Folgenden Code nutzt AppDomain.AssemblyResolve -
// register to listen to all assembly resolving attempts:
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
// Check whether the desired assembly is already loaded
private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args) {
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies) {
AssemblyName assemblyName = assembly.GetName();
string desiredAssmebly = args.Name;
if (assemblyName.FullName == desiredAssmebly) {
return assembly;
}
}
// Failed to find the desired assembly
return null;
}