Come posso implementare i plugin .net senza utilizzare AppDomains?

Istruzione del problema: implementare un sistema plug-in che consenta la sovrascrittura degli assembly associati (evitare il blocco dei file). In. Net, gli assembly specifici non possono essere scaricati, solo gli AppDomain completi possono essere scaricati.

Sto postando questo perché quando stavo cercando di risolvere il problema, ogni soluzione faceva riferimento all’utilizzo di più AppDomain. Più AppDomain sono molto difficili da implementare correttamente, anche se sono stati progettati all’inizio di un progetto.

Inoltre, AppDomains non ha funzionato per me perché avevo bisogno di trasferire Type tra domini come impostazione per l’attività InvokeWorkflow di worfklow. Sfortunatamente, l’invio di un tipo attraverso domini fa sì che l’assembly venga iniettato nell’AppDomain locale.

Inoltre, questo è rilevante per IIS. IIS ha un’impostazione Shadow Copy che consente di sovrascrivere un assembly in esecuzione mentre è caricato in memoria. Il problema è che (almeno in XP, non ha eseguito test sui server di produzione 2003) quando si carica un assembly a livello di codice, la copia shadow non funziona (perché si sta caricando la DLL, non IIS).

  1. Controllare se il gruppo è già stato caricato (per evitare perdite di memoria causate dal caricamento dello stesso assieme più e più volte).
  2. Se non è caricato, leggere l’assembly in una matrice di byte. Ciò impedirà il blocco del file.
  3. Fornire l’array di byte come argomentazione a Assembly.Load

Il seguente codice presuppone che tu conosca il FullName di un assembly.

Assembly assembly = null; foreach(Assembly loadedAssembly in AppDomain.CurrentDomain.GetAssemblies()) if (loadedAssembly.FullName == "foobar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null") assembly = loadedAssembly; if(assembly == null) { byte[] studybin = System.IO.File.ReadAllBytes(@"C:\pathToAssembly\foobar.dll"); assembly = Assembly.Load(studybin); } 

Nota che se stai cercando di trovare un assembly specifico in una directory, puoi eseguire “System.Reflection.AssemblyName.GetAssemblyName (path);” per vedere se FullName corrisponde a quello che stai cercando. ‘GetAssemblyName (path)’ NON inserisce l’assembly nel tuo AppDomain corrente.

Si noti inoltre che questa soluzione non è appropriata per le applicazioni che devono essere riavviate solo raramente E gli assiemi cambiano con l’alta frequenza. Ogni volta che viene caricato un assieme, l’ingombro di memoria della tua applicazione aumenterà. Non esiste un metodo per scaricare un assembly, quindi l’unica opzione per ridurre l’utilizzo della memoria è riavviare l’applicazione. Tuttavia, questa limitazione è spesso preferibile alle grandi prestazioni, alla memoria e al sovraccarico della complessità del codice dell’utilizzo di più domini dell’app. Questa limitazione è anche inevitabile se si desidera lavorare con Type s.

Se vuoi isolare i tuoi componenti aggiuntivi, devi …

  1. Crea un tipo che estende MarshallByRefObject che interagirà con i tuoi componenti aggiuntivi (chiamiamolo FOOMASTER)
  2. Crea un nuovo appdomain (chiamiamolo addinLand)
  3. Chiama addinLand.CreateInstanceAndUnwrap per creare un’istanza di FOOMASTER in addinLand e ottenere un proxy nel dominio dell’app corrente
  4. Dì a FOOMASTER di caricare i tuoi componenti aggiuntivi

Ora i tuoi addin sono caricati in addinLand e puoi interagire con loro dal tuo appdomain principale tramite il tuo proxy FOOMASTER. Quando i tuoi plugin si bloccano, non rimuovono la tua applicazione.

È un processo interessante e un po ‘confuso. Inizialmente pensavo che l’idea fosse di caricare i tuoi addin e poi portarli nel dominio delle app corrente come proxy trasparenti, ma il miglior design è di lasciare gli add-on come oggetti semplici che interagiscono con i tipi più complessi che crei (FOOMASTER), che estendono MarshallByRefObject, che vengono caricati nel dominio di app addinLand e con i proxy trasparenti con cui interagisci.

I capitoli 21 e 22 di CLR Via C # sono molto utili per comprendere il processo.

Se sei interessato a un metodo serio per la creazione di un sistema con un’architettura di plugin, ti consigliamo di controllare MAF (Managed Add-in Framework), che ora fa parte di .NET Framework, ovvero lo spazio dei nomi System.AddIn.

Ti aiuterà a gestire l’isolamento e il controllo delle versioni dei componenti aggiuntivi, persino la compatibilità con i contratti.

C’è comunque un po ‘di curva di apprendimento, quindi potrebbe non essere esattamente quello che stai cercando.

http://msdn.microsoft.com/en-us/library/bb384200.aspx