6 Stimmen

Laden von Assemblies in eine separate AppDomain, Erhalt einer InvalidCastException

Ich versuche, Baugruppen in einer separaten App-Domäne zu laden, stoße aber auf ein sehr seltsames Problem. Hier ist etwas Code:

    public static void LoadAssembly(string assemblyPath)
    {

        string pathToDll = Assembly.GetCallingAssembly().CodeBase;
        AppDomainSetup domainSetup = new AppDomainSetup
        {
            PrivateBinPath = pathToDll
        };

        AppDomain newDomain = AppDomain.CreateDomain("AssemblyLoader",null,domainSetup);

        AssemblyLoader loader = (AssemblyLoader)newDomain.CreateInstanceFromAndUnwrap(
            pathToDll,
            typeof(AssemblyLoader).FullName);

    }

AssemblyLoader ist eine andere Klasse in der gleichen Baugruppe wie diese, und es erbt von MarshalByRef, jedoch aus irgendeinem seltsamen Grund, bekomme ich eine Cast-Ausnahme jedes Mal, wenn ich versuche, dies auszuführen. Ich habe sogar den Pfad zur DLL hartcodiert, anstatt GetCallingAssembly().CodeBase zu verwenden, aber ich erhalte immer noch diese Ausnahme.

Ich weiß, dass es schwierig ist, eine Frage wie diese zu beantworten, ohne sie tatsächlich gesehen zu haben und über mehr Informationen zu verfügen, aber vielleicht ist jemand in eine ähnliche Situation geraten und kennt die üblichen "Fallstricke" und weiß, worauf ich achten sollte.

EDIT: Der Grund, warum ich nicht wollen, um es direkt zu laden ist, weil dies nur ein Teil des Codes ist. Das ultimative Ziel ist, dass diese Klasse eine Methode haben wird, die Assemblies laden, bekommt ihre GUID und einige andere Informationen über sie und speichert sie in einer Datenbank für ein Projekt, das ich arbeite. Wenn ich also diese Baugruppe in eine separate App-Domäne lade, kann ich die anderen auch dort laden und dann die App-Domäne entladen. Es macht keinen Sinn, alle diese Baugruppen für die Dauer der Anwendung zu laden, wenn ich nur diese Daten benötige.

2voto

user7116 Punkte 61589

(EDIT: nach dem Lesen der gegebenen Ausnahmeregelung wurde die Antwort vollständig geändert)

Das Problem scheint der CreateInstanceFromAndUnwrap-Aufruf zu sein, der die LoadFrom-Semantik von "pathToDll" verwendet. Suzanne Cook erläuterte den möglichen Knackpunkt in ihrem Blog, wo Ihre ursprüngliche AppDomain versucht, Load("SomeAssembly, [...]") im Gegensatz zu LoadFrom("pathToDll") aufzurufen, wenn sie versucht, den fraglichen Typ aufzulösen.

Ihr Rat war, das AssemblyResolve-Ereignis auf der aktuellen Domäne zu haken, um das richtige LoadFrom zu tun, um den Typ zu erhalten. Ein wenig zielgerichtetes Googeln führt zu folgenden Ergebnissen eine mögliche Lösung für das Problem auf der Grundlage von Suzannes Anregung.

0voto

TheXenocide Punkte 998

Ich glaube nicht, dass die PrivateBinPath-Konfiguration notwendig ist, darüber hinaus müssen Sie nicht den Pfad zur DLL, sondern den voll qualifizierten Namen der Assembly für den ersten Parameter verwenden; versuchen:

AssemblyLoader loader = (AssemblyLoader)newDomain.CreateInstanceFromAndUnwrap(
        typeof(AssemblyLoader).Assembly.FullName,
        typeof(AssemblyLoader).FullName);

0voto

Joseph Daigle Punkte 46087

Hier gibt es eine Menge guter Informationen für Ihr Vorhaben: Wie lädt man eine .NET-Assembly für Reflexionsoperationen und entlädt sie anschließend?

0voto

Jason D Punkte 2282

Überprüfen Sie diesen Artikel.

Mit dem Code in diesem Artikel habe ich ein domänenübergreifendes Objekt erhalten. Ich abstrahiert Dinge ein bisschen mit Generika und haben drei Baugruppen. (d.h. 1, die die Schnittstelle definiert, 1, die die Plugin-Implementierung definiert, und das Hauptprogramm, das der Generik sagt, was zu laden ist). Der Code des Originalartikels ist leicht zu verstehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X