La nostra applicazione non fa ancora nulla ma almeno si avvia.
Il prossimo passo è quello di realizzare un’infrastruttura per gestire i moduli, in particolare in questa fase ci concentreremo sul processo di discovery.
Quali sono i problemi che dobbiamo risolvere:
- Discovery: il processo di discovery è quello che consente all’IApplicationBootstrapper di capire quali siano i moduli che possono essere caricati, quello che ci dobbiamo limitare a fare è quindi fornire allo strato superiore l’elencodeii moduli disponibili, non è onere nostro fare nessun ragionamento;
A questo punto possiamo avere 3 potenziali problemi:
- Un requisito potrebbe essere che l’utente deve poter scegliere se caricare o meno un certo modulo;
- Potremmo introdure il concetto di moduli “esclusivi”, quindi un solo modulo di tipo esclusivo può essere caricato;
- Potremmo aver bisogno di fare ragionamenti sulla base dei moduli disponibili e prendere decisioni su cosa caricare e in che modo;
- Descriptors Loading: i potenziali scenari descritti ci obbligano a scindere le informazioni che descrivono il modulo e ad “esternalizzarle” dall’assembly che definisce il modulo stesso, in questo modo possiamo evitare di caricare nell’AppDomain l’assembly, dato che poi non potremmo scaricarlo, e possiamo evitare di mettere in piedi complessi castelli per effettuare il caricamento in un AppDomain diverso da quello del chiamante;
Discovery & Descriptors Loading
Il processo di discovery, come abbiamo detto, è l’atto di scoprire quali siano i moduli installati, potremmo sintetizzarlo così:
var moduleManager = serviceContainer.Resolve<IModuleManager>();
var installedModules = moduleManager.GetInstalledModules();
Il metodo GetInstalledModules() ci ritorna una IEnumerable<IModuleDescriptor>; una classe che implementa IModuleDescriptor altro non è che una banalissima classe che contiene informazioni relative ad un determinato modulo, ora come ora semplicemente:
interface IModuleDescriptor
{
String Name{ get; }
}
banale direi, per ora del resto non ci serve altro.
Il processo di caricamento dei ModuleDescriptor(s) è implementato utilizzando come repository, della configurazione dei moduli installati, il file di configurazione dell’applicazione stessa. Quindi, nella nuova versione della solution, trovete un’implementazione di IModuleManager che dipende da una ConfigurationSection (System.Configuration) che è in grado di gestire le informazioni persistite all’interno del file app.config.
Quindi quello che trovate è:
- ModuleDescriptor: implementa l’interfaccia IModuleDescriptor e espone informazioni, descrittive, relative ad un modulo;
- ConfigSectionModuleManager: implementa l’interfaccia IModuleManager e gestisce, per ora, il solo discovery dei moduli installati, ConfigSectionModuleManager dipende dalla configurazione presente nel file app.config dell’applicazione;
- ModulesConfigurationSectionHandler: implementa la logica per deserializzare le informazioni custom presenti nel file di configurazione relative ai moduli installati;
- ModuleElement e ModuleCollectionElement gesticono, rispettivamente, il singolo elemento definito all’interno del file di configurazione e una lista di elementi;
Ho infine introdotto il primo servizio “applicativo” che potrà essere utilizzato da tutti i moduli e dalla Shell stessa:
- IEnvironmentService: che in questo momento consente di accedere alla lista dei moduli installati;
Naturalmente l’altra variazione di rilievo è nel progetto MyApplication.Boot in cui abbiamo aggiornato la configurazione di Castle Windsor al fine di fargli gestire il discovery dei nuovi servizi.
Allego il progetto con le modifiche descritte: CompositeUI_v2.zip
C’è infine un nuovo progetto, Castle.Extensibility, non contiene altro che una extension che serve per gestire in maniera più umana le factory con Castle Windsor, il codice, peraltro molto semplice, non è frutto del mio sacco ma sinceramente non ricordo dove l’ho trovato quindi non posso citare la fonte, mi spiace.
.m