Nella versione corrente (Preview 9), MEF ci mette a disposizione quattro Catalog per effettuare il discovery delle ComposablePart.
- AssemblyCatalog: effettua lo scan dell’assembly specificato
- TypeCatalog: effettua il discovery degli export dei tipi specificati
- DirectoryCatalog: effettua lo scan di tutti gli assembly presenti nella cartella specificata. Lo scan verrà eseguito solo una volta per cui se vengono aggiungi degli assembly nella directory il DirectoryCatalog non si accorgera’ di nulla. Se vogliamo rieffettuare lo scan basta chiamare il metodo Refresh
- AggregateCatalog: come si puo’ intuire dal nome permette di combinare piu’ cataloghi insieme. Si possono aggiungere i Catalogs tramite il costruttore oppure usando aggregateCatalog.Catalogs.Add(…)
IMHO il DirectoryCatalog e’ molto utile, soprattutto se abbiamo dei plugins di terze parti che devono essere caricati da una folder specifica…per esempio Plugins :D
Pero’ i plugins vengono caricati dalla directory solo una volta per cui anche se ne aggiungiamo altri nessuno si accorge di nulla.
Cosi’ ho deciso di implementare un semplice DirectoryWatcherCatalog che sta allerta su quello che succede all’interno della directory specificata
1: public class DirectoryWatcherCatalog : DirectoryCatalog
2: {
3: private FileSystemWatcher watcher;
4: private delegate void DispatcherInvoker();
5:
6: private DispatcherInvoker refresher;
7:
8: public DirectoryWatcherCatalog(string path)
9: : this(path, "*.dll")
10: {
11: }
12:
13: public DirectoryWatcherCatalog(string path, string pattern) : base(path, pattern)
14: {
15: refresher = new DispatcherInvoker(() => base.Refresh());
16:
17: watcher = new FileSystemWatcher(path);
18: watcher.Filter = pattern;
19: watcher.Changed += new FileSystemEventHandler(watcher_Changed);
20: watcher.EnableRaisingEvents = true;
21:
22: }
23:
24: private void watcher_Changed(object sender, FileSystemEventArgs e)
25: {
26: Application.Current.Dispatcher.Invoke(refresher);
27: }
28:
29: protected override void Dispose(bool disposing)
30: {
31: base.Dispose(disposing);
32:
33: watcher.EnableRaisingEvents = false;
34: watcher.Changed -= watcher_Changed;
35: watcher.Dispose();
36:
37: watcher = null;
38: }
39: }
Non penso che il codice abbia bisogno di molte spiegazioni visto che l’unica cosa che fa è aspettare che succeda qualcosa all’interno della directory monitorata e richiamare il metodo Refresh della classe DirectoryCatalog che andrà ad effettuare lo scan della directory.
Nei prossimi post andremo a vedere come creare un catalog personalizzato partendo da zero quindi ereditando ed implementando: ComposablePartCatalog, ICompositionElement e INotifyComposablePartCatalogChanged.