Around and About .NET World

Il blog di Marco Minerva
posts - 1671, comments - 2232, trackbacks - 2135

My Links

News

Contattami su Live Messenger:


MCTS: Windows, Web, Distributed Applications & SQL Server

MCPD: Enterprise Applications

Tag Cloud

Archives

Post Categories

Links

Caricamento di DLL in AppDomain diversi

Quando si deve realizzare un sistema basato su plug-in, è buona norma utilizzare un AppDomain diverso per caricare le estensioni, in modo che un plug-in mal funzionante non possa compromettere il funzionamento dell'intera applicazione. La soluzione che adotto io si basa su una classe chiamata AssemblyLoader:

1 using System; 2 using System.Reflection; 3 4 namespace System.Reflection 5 { 6 public class AssemblyLoader : MarshalByRefObject 7 { 8 public AssemblyLoader() 9 { } 10 11 public object CreateInstance(string assemblyName, 12 string interfaceName, params object[] args) 13 { 14 try 15 { 16 Assembly assembly = Assembly.LoadFrom(assemblyName); 17 foreach (Type type in assembly.GetExportedTypes()) 18 { 19 Type interfaceType = type.GetInterface(interfaceName); 20 if (interfaceType != null) 21 return Activator.CreateInstance(type, args); 22 } 23 return null; 24 } 25 catch 26 { 27 return null; 28 } 29 } 30 } 31 }

Il cuore della classe è il metodo CreateInstance, che controlla i tipi esportati da un certo assembly (riga 17), quindi crea un'istanza del tipo che implementa l'interfaccia passata come argomento (righe 19-21).

Tale classe deve essere compilata in una class library. A questo punto, per caricare un plug-in in un nuovo AppDomain è sufficiente scrivere qualcosa del tipo:

AppDomain pluginAppDomain = AppDomain.CreateDomain("Plug-in AppDomain"); AssemblyLoader loader = (AssemblyLoader)pluginAppDomain.CreateInstanceFromAndUnwrap ("AssemblyLoader.dll", typeof(AssemblyLoader).FullName); IPlugin plugin = (IPlugin) loader.CreateInstance(AppDomain.CurrentDomain.BaseDirectory + @"\Plugins\TestPlugin.dll", "IPlugin");

L'oggetto loader viene caricato nell'AppDomain chiamato Plug-in AppDomain. IPlugin è l'interfaccia che deve essere implementata da ogni plug-in; ogni plug-in, inoltre, deve estendere la classe MarshalByRefObject. Il nome dell'interfaccia deve essere passato come secondo argomento alla funzione AssemblyLoader.CreateInstance. Il risultato di questo codice è l'istanziazione della classe che implementa IPlugin (e che è contenuta in TestPlugin.dll) all'interno del nuovo AppDomain. In tal modo, richiamando sull'oggetto plugin i metodi che sono definiti nell'interfaccia IPlugin, essi verranno eseguiti all'interno del Plug-in AppDomain.

Utilizzando questa strategia, se il plug-in manifesta qualche problema è sufficiente scaricare l'AppDomain che lo contiene, senza essere costretti ad interrompere l'intera applicazione.

Print | posted on Sunday, January 28, 2007 2:55 PM | Filed Under [ C# ]

Feedback

Gravatar

# re: Caricamento di DLL in AppDomain diversi

Caricando l'assembly anche nell'AppDomain principale:

Assembly.LoadFrom(assemblyFullPath);

prima di creare il nuovo AppDomain e passargli l'assemblyloader, l'istanza viene passata correttamente ma solo se passata come object:

object pluginInstance = pluginLoaderInstance.CreateInstance(assemblyFullPath,
"IPluginInterface",
null);

se uso:
IPluginInterface pluginInstance = (IPluginInterface)pluginLoaderInstance.CreateInstance(assemblyFullPath,
"IPluginInterface", null);

mi da:
System.InvalidCastException: Cannot cast from source type to destination type.
8/23/2009 11:22 AM | Armando Basile
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET