Ich musste dies mehrmals tun und habe viele verschiedene Lösungen recherchiert.
Die Lösung, die ich am elegantesten und am einfachsten zu realisierenden finde, kann als solche implementiert werden.
1. Erstellen Sie ein Projekt, mit dem Sie eine einfache Schnittstelle erstellen können
Die Schnittstelle enthält Signaturen aller Mitglieder, die Sie anrufen möchten.
public interface IExampleProxy
{
string HelloWorld( string name );
}
Es ist wichtig, dieses Projekt sauber und einfach zu halten. Es ist ein Projekt, auf das beide AppDomain
verweisen können und das es uns ermöglicht, nicht auf das zu verweisen, das Assembly
wir in einer separaten Domäne von unserer Client-Assembly laden möchten.
2. Erstellen Sie nun ein Projekt mit dem Code, den Sie separat laden möchten AppDomain
.
Dieses Projekt verweist wie das Client-Projekt auf das Proxy-Projekt und Sie implementieren die Schnittstelle.
public interface Example : MarshalByRefObject, IExampleProxy
{
public string HelloWorld( string name )
{
return $"Hello '{ name }'";
}
}
3. Laden Sie als Nächstes im Client-Projekt den Code in einen anderen AppDomain
.
Also, jetzt schaffen wir eine neue AppDomain
. Kann den Basisort für Baugruppenreferenzen angeben. Bei der Prüfung wird nach abhängigen Assemblys im GAC und im aktuellen Verzeichnis sowie in der AppDomain
Basislok gesucht.
// set up domain and create
AppDomainSetup domaininfo = new AppDomainSetup
{
ApplicationBase = System.Environment.CurrentDirectory
};
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
AppDomain exampleDomain = AppDomain.CreateDomain("Example", adevidence, domaininfo);
// assembly ant data names
var assemblyName = "<AssemblyName>, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null|<keyIfSigned>";
var exampleTypeName = "Example";
// Optional - get a reflection only assembly type reference
var @type = Assembly.ReflectionOnlyLoad( assemblyName ).GetType( exampleTypeName );
// create a instance of the `Example` and assign to proxy type variable
IExampleProxy proxy= ( IExampleProxy )exampleDomain.CreateInstanceAndUnwrap( assemblyName, exampleTypeName );
// Optional - if you got a type ref
IExampleProxy proxy= ( IExampleProxy )exampleDomain.CreateInstanceAndUnwrap( @type.Assembly.Name, @type.Name );
// call any members you wish
var stringFromOtherAd = proxy.HelloWorld( "Tommy" );
// unload the `AppDomain`
AppDomain.Unload( exampleDomain );
Wenn nötig, gibt es unzählige Möglichkeiten, eine Baugruppe zu laden. Mit dieser Lösung können Sie einen anderen Weg wählen. Wenn Sie den Assembly-qualifizierten Namen haben, verwende ich gerne den, CreateInstanceAndUnwrap
da er die Assembly-Bytes lädt und dann Ihren Typ für Sie instanziiert und einen zurückgibt object
, den Sie einfach in Ihren Proxy-Typ umwandeln können, oder wenn Sie dies nicht in stark typisierten Code tun könnten Verwenden Sie die dynamische Sprachlaufzeit und weisen Sie das zurückgegebene Objekt einer dynamic
typisierten Variablen zu. Rufen Sie dann einfach die Mitglieder direkt auf.
Hier hast du es.
Auf diese Weise können Sie eine Assembly laden, auf die Ihr Client-Projekt in einem separaten Verzeichnis nicht verweist, AppDomain
und Mitglieder vom Client darauf aufrufen.
Zum Testen verwende ich gerne das Modulfenster in Visual Studio. Es zeigt Ihnen Ihre Client-Assembly-Domäne und was alle Module in dieser Domäne geladen sind sowie Ihre neue App-Domäne und welche Assemblys oder Module in dieser Domäne geladen sind.
Der Schlüssel besteht darin, entweder sicherzustellen, dass der Code entweder abgeleitet MarshalByRefObject
oder serialisierbar ist.
Mit MarshalByRefObject können Sie die Lebensdauer der Domäne konfigurieren, in der sie sich befindet. Beispiel: Sie möchten, dass die Domäne zerstört wird, wenn der Proxy nicht innerhalb von 20 Minuten aufgerufen wurde.
Ich hoffe das hilft.