2012-10-26 14 views
12

Ich kämpfe seit einiger Zeit mit AssenblyResolve Event. Ich habe stackoverflow gesucht und andere googeln und alles versucht, was ich für relevant hielt. Hier sind die Links, je näher zu meinem Problem (meiner Meinung nach) zu sein:AssemblyResolve nicht für Abhängigkeiten gefeuert

  1. AssemblyResolve is not invoked and FileNotFoundException is thrown during serialization

  2. Where to handle AssemblyResolve event in a class library?

Ich habe eine Bootstrapper-Klasse mit statischer Methode (Ich werde entfernen der thread safe code, den wir haben, nur aus Gründen der Klarheit:

public static void Initialize() 
{ 
    AppDomain.CurrentDomain.AssemblyResolve += CustomResolve; 
} 

private static Assembly CustomResolve(object sender, ResolveEventArgs args) 
{ 
    // There is a lot code here but basicall what it does. 
    // Is determining which architecture the computer is running on and 
    // extract the correct embedded dll (x86 or x64). The code was based 
    // on milang on GitHub (https://github.com/milang/P4.net). And it's the same 
    // purpose we want to be able to load the x86 or x64 version of the perforce dll 
    // but this time with the officially Perforce supported p4api.net. 
    // Once the dll is extracted we assign it to the boostrapper 
    Bootstrapper._p4dnAssembly = Assembly.LoadFile(targetFileName); 

    // Make sure we can satisfy the requested reference with the embedded assembly (now extracted). 
    AssemblyName reference = new AssemblyName(args.Name); 
    if (AssemblyName.ReferenceMatchesDefinition(reference, Bootstrapper._p4dnAssembly.GetName())) 
    { 
     return Bootstrapper._p4dnAssembly; 
    } 
} 

Ich konnte den Code arbeiten lassen, wenn ich eine einfache Klasse mit einer Hauptmethode und einem statischen Konstruktor habe. Der statische Konstruktor ruft einfach die Boostrapper.Initialize() -Methode auf. Danach konnte ich meine Bibliothek verwenden und es funktioniert wie erwartet:

public static class Test 
{ 
    static Test() 
    { 
     Bootstrapper.Initialize(); 
    } 

    public static void Main() 
    { 
     // Using the library here is working fine. The AssemblyResolve event was 
     // fired (confirmed by a breakpoint in Visual Studio) 
    } 
} 

Das Problem, das ich habe, ist, wenn es mindestens eine Schicht der Abhängigkeit ist. Grundsätzlich bleibt der Code die gleichen, aber diesmal mein der Code der Bibliothek in einer anderen Bibliothek:

public static class Test 
{ 
    static Test() 
    { 
     Bootstrapper.Initialize(); 
    } 

    public static void Main() 
    { 
     Class1 myClass = new Class1(); 

     // The following line is using the code of the extracted library, but 
     // The AssemblyResolve event is not fired (or fired before I register the 
     // callback) and therefore the library is not found : result 
     // BadImageFormatException() error could not load libary because one 
     myClass.Connect(); 
    } 
} 

Klingt wie # 2 der Links, die ich bereits erwähnt habe erklären, was ich sehe, aber es funktioniert nicht . Der Visual Studio-Unterbrechungspunkt im AssemblyResove-Callback wird niemals getroffen.

Irgendeine Idee von was ist los?

Francis

Antwort

7

Jemand hat geantwortet, aber die Antwort wurde gelöscht. Also kann ich es nicht als beantwortet markieren. Grundsätzlich funktioniert die Tatsache, dass der Code nicht außerhalb der "Haupt" -Methode sein muss. startet frisch aus einem neuen Projekt, lösen das Problem so dass ich denke, ich mit der dll einige Probleme hatte (wahrscheinlich x86 DLL in x64-Ordner oder umgekehrt)

static void main(string[] args) 
{ 
    Boostrapper.Initialize(); 
    RealMain(); 
} 

static void RealMain() 
{ 
    Class1 myClass = new Class1(); 
    myClass.Connect(); 
} 
15

Ich weiß, dass es schon eine Weile her, seit dieser Frage war gefragt und beantwortet, aber ich wollte meine Aufnahme auf das Problem sowieso hinzufügen (da ich nur ein paar Stunden darüber verschwendet, vielleicht dank dieser jemand anderes würde nicht müssen)

Das Problem ist im Grunde die Tatsache, dass Die Anwendung versucht, alle Assemblys aufzulösen, die zum Ausführen der Methode am Anfang dieser Methode erforderlich sind:

static void main(string[] args) 
{ 
    // <-- here the app tries to resolve MyAssembly 
    // and as MyAssembly.Class1 is not found, the app crashes 

    // this next line is never called: 
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly); 

    // class contained in an assemnly that we need to resolve 
    MyAssembly.Class1 myClass = new MyAssembly.Class1(); 
} 

Aus diesem Grund stürzt das obige Ereignis ab: Der Event-Handler ResolveAssembly wird nie aufgerufen, weil er nie angeschlossen wurde.

Und das ist auch, warum die unten Lösung arbeitet (wie von der OP geschrieben):

static void main(string[] args) 
{ 
    Initialize(); 
    RealMain(); 
} 

static void Initialize() 
{ 
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ResolveAssembly); 
} 

static void RealMain() 
{ 
    // <-- here the app tries to resolve MyAssembly 
    // class contained in an assemnly that we need to resolve  
    MyAssembly.Class1 myClass = new MyAssembly.Class1(); 
    // and everything is OK 
} 
Verwandte Themen