MEF & AppDomains

Da un pò di tempo sto cercando di far caricare a MEF gli exports (plugins) in un AppDomain secondario (con tutti i pro e contro che questo comporta) e pian piano qualcosa sta venendo fuori...



Stay tuned...

Filtering Exports with FilteredCatalog

MEFContrib è un progetto creato da Glenn Block ed altre persone note in cui inseriscono alcune chicche che possono essere utili quando si utilizza MEF ad esempio:

1) un catalog che supporta gli open generics (MEF di default supporta solo i closed generics)
2) un catalog che ci permette di filtrare gli exports
3) integrazione con Unity
4) un “botto” di cose che non ho la minima idea a cosa servano :)

In questo post vedremo un esempio che mostra un utilizzo del FilteredCatalog!

Scenario:

Abbiamo un’interfaccia ILogger che rappresenta un logger generico che ci permette di loggare un exception


Abbiamo un paio di implementazioni, molto farlocche, e vogliamo che solo quella “marcata come default” venga importata!

Soluzioni:

1) Chiediamo a MEF di importare tutte le implementazioni di ILogger e poi ce le filtriamo noi
2) Utilizziamo il FilteredCatalog che ci mette a disposizione MEFContrib

Mi sembra ovvio, visto il titolo del post, che adotteremo la seconda soluzione :)

FilteredCatalog ci offre due costruttori:


Il primo parametro, uguale per entrambi i costruttori, è il catalog da cui verranno ricavati gli exports, se abbiamo più catalogs possiamo usare un AggregateCatalog. Il secondo parametro è il nostro filtro, possiamo specificare una lambda expression oppure implementare l’interfaccia IFilter. MEFContrib offre due implementazioni di IFilter, una che ci permette di filtrare sui metadata o meglio su PartMetadataAttribute, poi vedremo cos’è, e l’altro che ci dice se la composable part definisce una determinata CreationPolicy.

Di seguito vediamo i due logger; entrambi implementano ILogger, sono marcati con l’attributo Export e PartMetadata. Quest’ultimo ci consente di assegnare alla ComposablePart (quel famoso oggetto che può contenere imports e exports e con cui lavorano i catalogs) dei metadata (informazioni aggiuntive). In questo caso creiamo un nuovo metadata, “Logger”, e sul primo logger lo settiamo a true mentre sul secondo a false.


PartMetadata verrà utilizzato dal FilteredCatalog, ed in particolare dall’implementazione che abbiamo utilizzato di IFilter per ottenere solo un’implementazione di ILogger e cioè quella di default.

Quando creiamo il FilteredCatalog, oltre al catalog da dove recuperare gli exports su cui filtrare, gli passiamo un’istanza di ContainsMetadata che non fa altro che controllare se
il metadata specificato, “Logger” in questo caso, esista e se il valore corrispondente è uguale a true.


Nei prossimi post vedremo altre cose interessanti di MEFContrib, per poi capire come caricare i nostri plugin/export su un AppDomain secondario ;)