Ho dovuto farlo diverse volte e ho cercato molte soluzioni diverse.
La soluzione che trovo più elegante e di facile realizzazione può essere implementata come tale.
1. Creare un progetto che è possibile creare una semplice interfaccia
l'interfaccia conterrà le firme di tutti i membri che desideri chiamare.
public interface IExampleProxy
{
string HelloWorld( string name );
}
È importante mantenere questo progetto pulito e leggero. È un progetto a cui entrambi AppDomain
possono fare riferimento e ci permetterà di non fare riferimento a quello Assembly
che desideriamo caricare in un dominio separato dal nostro assembly client.
2. Ora crea il progetto che ha il codice che vuoi caricare separatamente AppDomain
.
Questo progetto come con il progetto del cliente farà riferimento al progetto proxy e implementerai l'interfaccia.
public interface Example : MarshalByRefObject, IExampleProxy
{
public string HelloWorld( string name )
{
return $"Hello '{ name }'";
}
}
3. Successivamente, nel progetto client, caricare il codice in un altro AppDomain
.
Quindi, ora creiamo un nuovo file AppDomain
. Può specificare la posizione di base per i riferimenti di assieme. L'analisi verificherà la presenza di assembly dipendenti in GAC e nella directory corrente e nella posizione di AppDomain
base.
// 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 );
se necessario, ci sono molti modi diversi per caricare un assieme. Puoi usare un modo diverso con questa soluzione. Se hai il nome qualificato dell'assembly, mi piace usare CreateInstanceAndUnwrap
poiché carica i byte dell'assembly e quindi istanzia il tuo tipo per te e restituisce un object
che puoi semplicemente trasmettere al tuo tipo di proxy o se non lo fai in codice fortemente digitato potresti utilizzare il runtime del linguaggio dinamico e assegnare l'oggetto restituito a una dynamic
variabile digitata, quindi chiamare direttamente i membri su quella.
Ecco qua.
Ciò consente di caricare un assembly a cui il progetto client non ha riferimento in un separato AppDomain
e chiamare membri su di esso dal client.
Per testare, mi piace usare la finestra Moduli in Visual Studio. Ti mostrerà il dominio dell'assembly client e quali sono tutti i moduli caricati in quel dominio, nonché il tuo nuovo dominio dell'app e quali assembly o moduli vengono caricati in quel dominio.
La chiave è assicurarsi che il codice derivi MarshalByRefObject
o sia serializzabile.
`MarshalByRefObject ti permetterà di configurare la durata del dominio in cui si trova. Esempio, supponi di voler distruggere il dominio se il proxy non è stato chiamato in 20 minuti.
Spero che aiuti.