Posts
163
Comments
179
Trackbacks
5
dicembre 2011 Blog Posts
Eseguire un assembly in un AppDomain separato

 Nello sviluppo di architetture a plugin può diventare necessario eseguire assembly in un AppDomain separato, magari recuperando gli assembly (con relative dipedenze) da una sottocartella.
In rete si trovano tantissimi esempi, che usano metodi recenti o datati e che sfruttano varie tecniche. Sono però riuscito ad arrivare ad una soluzione che mi soddisfacesse, solo dopo molti tentativi e molte ricerche e quindi mi sembra giusto condividere i risultati della mia ricerca sperando che possano facilitare la vita a qualcuno.

Prima di andare avanti vorrei però esplicitare le mie necessità:

- Eseguire i metodi di una o più classi contenute all’interno di un assembly, in un AppDomain separato;
- Poter caricare nell’AppDomain assembly con reference ad altri assembly “locali” o memorizzati nella GAC; 
- Memorizzare l’assembly (con tutte le sue dipendenze) in una sotto directory;
- Poter passare parametri al costruttore delle classi da creare.
 
La funzione seguente, seppur molto semplice, soddisfa tutte le mie necessità:

   1: Public Sub ExecuteOnAppDomain(ByVal typeName As String, ByVal assemblyName As String)
   2:     Dim domainSetup As AppDomainSetup = New AppDomainSetup
   3:     domainSetup.ApplicationBase = Environment.CurrentDirectory
   4:     domainSetup.PrivateBinPath = "RELATIVE_FOLDER"
   5:     ' Copia delle policy dall'appdomain corrente
   6:     Dim adevidence As Evidence = AppDomain.CurrentDomain.Evidence
   7:     ' Creazione nuovo appdomain
   8:     Dim domain As AppDomain = AppDomain.CreateDomain("SomeAppDomain", adevidence, domainSetup)
   9:  
  10:     ' Argomenti costruttore
  11:     Dim constructorArgs As New List(Of Object)
  12:     constructorArgs.Add("PARAM1")
  13:     ' ....
  14:     ' ....
  15:     constructorArgs.Add(10)
  16:     ' Bindings
  17:     Dim bindings = BindingFlags.CreateInstance Or BindingFlags.Instance Or BindingFlags.Public
  18:     ' Creazione della classe dato il nome completo e l'assembly di riferimento
  19:     Dim obj = domain.CreateInstanceAndUnwrap(assemblyName, typeName, False, bindings, Nothing,
  20:                                              constructorArgs.ToArray, Nothing, Nothing, Nothing)
  21:     obj.DoWork()
  22:     ' Unload dell'appdomain
  23:     AppDomain.Unload(domain)
  24:   End Sub


Alcune note:

- Nella proprietà PrivateBinPath dell’AppDomainSetup è possibile specificare le sottodirectory da utilizzare per il probing degli assembly;
- I parametri del costruttore devono essere specificati nello stesso ordine e devono avere lo stesso tipo di quelli presenti nel costruttore della classe da istanziare;
- L’assembly name non deve contenere il suffisso “.dll” ma solo il nome dell’assembly;
- Il typeName deve contenere il nome completo del tipo della classe da istanziare;
- Tutti gli assembly referenziati devono essere inseriti nelle sottodirectory o nella directory principale del nostro applicativo (o nella GAC);
- La risoluzione delle dipendenze viene fatta in automatico senza dover implementare nessun meccanismo manuale di risoluzione.

posted @ venerdì 2 dicembre 2011 12:16 | Feedback (0)
News
Se volete sapere con chi avete a che fare eccomi qui in uno "scatto" lavorativo.

La mia foto

Logo MCAD
Logo MCTS