MEFedMVVM Composition & IComposer

Piccola nota: prima di leggere questo post si consiglia di dare un occhio ai due precedenti

http://blogs.ugidotnet.org/federicoD/archive/2010/09/09/mef-mvvm-mefedmvvm.aspx
http://blogs.ugidotnet.org/federicoD/archive/2011/01/27/caricare-assembly-non-referenziati-con-mefedmvvm.aspx

Chi ha già usato MEFedMVVM saprà benissimo che una volta dato un nome ai nostri ViewModel e, dopo aver specificato nelle View quale ViewModel ci serve, “qualcuno” si occuperà di far combaciare e funzionare tutto l’ambaradan.

Questo “qualcuno” è il LocatorBootstrapper, che insieme agli IComposers si occuperà di effettuare la composition. In particolare IComposer si occupa di definire quali sono i Catalogs da usare, per cui dove MEF andrà a cercare ViewModel, Services, e via dicendo, e ci consente anche di specificare se usare degli ExportProvider custom.

image

Il ComposablePartCatalog viene utilizzato dal LocatorBootstrapper come Catalog principale dove cercare tutte le ComposablePart, per cui, creando un’implementazione custom di IComposer possiamo dire, ad esempio, a MEFed di cercare su una cartella diversa da Extensions, su assembly diversi, etc…

Ora vediamo di capire perchè ci può servire un’implementazione nostra di IComposer. L’applicazione che utilizzeremo come esempio è la stessa usata nel post precedente … con qualche modifica.

image

MEFedMVVMDemo è la nostra applicazione WPF che conterrà l’App.xaml ed il composer customizzato, gli altri progetti direi che sono abbastanza autoesplicativi.

MEFed offre già un Message Broker ed un ViewModel di base, ma noi vogliamo usare MvvmLight Sorriso Nell’esempio iniziale, nel costruttore dei ViewModels richiedevamo IMediator (presente in MEFed), ora lo sostituiamo con IMessenger (presente in MvvmLight).
Però c’è un piccolo problema…l’implementazione di IMessenger non è marcata con l’attributo ExportService, per cui MEFed non sarà in grado di istanziare i ViewModels e quindi il processo di composition fallirà.

Visto che non siamo in grado di marcare l’implementazione di IMessenger con l’attributo ExportService, una soluzione è di creare una nostra implementazione di IComposer e creare un ExportProvider che quando “vede” che MEF sta richiedendo l’implementazione di IMessenger la restituisca.

Partiamo col vedere la classe CustomComposer che implementa IComposer. Il metodo GetCustomExportProviders ritornerà una lista contenente i nostri ExportProvider; InitializeContainer ci consente di specificare il catalog utilizzato per la composition.

image

Il metodo GetCatalog andrà a creare un AggregateCatalog a cui verranno aggiunti i Catalog che servono a MEF per trovare i vari pezzi. In questo caso aggiungiamo l’Assembly contente MEFed (questo ci potrebbe servire nel caso volessimo usare i servizi offerti, es. IVisualStateManager, IContainerStatus, …) e un DirectoryCatalog per caricare le varie dipendenze, come ad esempio MEFedMVVM.Demo.ViewModels, MEFedMVVM.Demo.Services e MEFedMVVM.Demo.Interfaces, dalla cartella Extensions.

CustomExportProvider si occuperà di soddisfare la dipendenza verso IMessenger, per cui quando viene richiesto un Import dove il ContractName è uguale al FullName del type IMessenger creiamo un Export e lo aggiungiamo alla lista degli Export che verrà ritornata.

image

Bene ora non ci rimane che dire al LocatorBootstrapper di utilizzare il nostro Composer

image

I sorgenti li potete scaricare da qui Sorriso