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 AppDomainpossono fare riferimento e ci permetterà di non fare riferimento a quello Assemblyche 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 AppDomainbase.
// 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 CreateInstanceAndUnwrappoiché carica i byte dell'assembly e quindi istanzia il tuo tipo per te e restituisce un objectche 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 dynamicvariabile 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 AppDomaine 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 MarshalByRefObjecto 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.