MEF + MVVM = MEFedMVVM

MEFedMVVM è un framework sviluppato da Marlon Grech che utilizza MEF per comporre i ViewModel con le rispettive View, tenendovi però all’oscuro di tutta la parte di MEF. Una frase che mi è subito saltata all’occhio da uno dei tanti articoli di Marlon su MEFedMVVM è:

One of the goals of MEFedMVVM  is to do all the MEF plumbing for you so that you can simple say “I want to Export this ViewModel” and then you can have a View that says “I would like that specific ViewModel” and BANG, MEFedMVVM will do all the plumbing by leveraging the Mighty MEF.

MEFedMVVM può essere utilizzato sia con WPF che con Silverlight e per gli amanti di Blend supporta benissimo i DesignTime data :)

In questo articolo vedremo soltanto le basi di questo framework, per cose più avanzate potete leggere gli articoli di Marlon che trovate alla fine insieme al link per il download.

I want to Export this ViewModel

Per dire a MEFedMVVM che una determinata classe è un ViewModel basta utilizzare l’attributo ExportViewModel passando come parametro il nome che gli vogliamo assegnare.

image

NotifyPropertyChanged è solo ed esclusivamente un’implementazione di INotifyPropertyChanged. MEFedMVVM, seppur il nome potrebbe ingannare, non è un vero e proprio framework MVVM, anzi, lascia la libertà di utilizzare qualsiasi framework MVVM che si voglia :)

I would like that specific ViewModel

Ora abbiamo uno UserControl, una Window, bè una View a cui dobbiamo associare il ViewModel precedentemente creato

image

Le due parti che ci interessano sono evidenziate in nero:

1) Importiamo il namespace di MEFedMVVM
2) Diciamo a MEFedMVVM quale ViewModel vogliamo, in questo caso MainViewModel è il ViewModel che abbiamo definito in precedenza

Ora possiamo “bindare” qualsiasi proprietà del nostro MainViewModel a qualsiasi FrameworkElement della nostra View :)

image 

Quando avvieremo l’applicazione MEFedMVVM si occuperà di “configurare” MEF che assocerà gli Exports ai relativi Imports

image

Questa sintassi definisce un Import :)

E se il nostro ViewModel dovesse recuperare dei dati da un database o da qualche altre parte?!? Bè potremmo creare un servizio che sia in grado di recuperare i dati che ci interessano e lo iniettiamo nel costruttore del ViewModel…niente di più semplice!

image

Creiamo un’interfaccia per il nostro servizio in questo caso IAccomodationService, lo inseriamo come parametro del costruttore, marchiamo il costruttore con l’attributo ImportingConstructor, creiamo una classe che implementi IAccomodationService,

image 

la marchiamo con l’attributo ExportService specificando se questo servizio deve essere usato a runtime o a design time ed il gioco è fatto :)

Il costruttore di MainViewModel, oltre a IAccomodationService, ha anche come parametro IMediator. IMediator è un’interfaccia di MEFedMVVM che implementa un Message Broker in maniera tale che possiamo spedire messaggi/notifiche a destra e a manca.

Prima avevamo accennato che MEFedMVVM supporta benissimo i DesignTime data…verissimo!

Se un ViewModel ha qualche proprietà in binding con la View e nel costruttore del ViewModel valorizziamo le varie proprietà, in Blend i valori che abbiamo dato verranno visualizzati perfettamente! Infatti verrà fatta una specie di Composition a DesignTime associando i ViewModels con le rispettive Views!

image

Il metodo LoadAccomodations, nel costruttore del MainViewModel, non fa altro che richiedere la lista di Accomodation da IAccomodationService ed aggiungerle ad un ObservableCollection in binding con la View.

Sorge spontanea una domanda: come fa MEFedMVVM ad iniettare l’AccomodationService, o meglio come farà l’AccomodationService ad accedere al db a DesignTime???

Risposta: non lo fa :D In realtà dobbiamo creare un servizio che possa essere utilizzato a DesignTime

image

Creiamo un’altra implementazione di IAccomodationService, la decoriamo con ExportService solo che questa volta specifichiamo che deve essere utilizzato a DesignTime tramite ServiceType.DesignTime. Infine creiamo qualche oggetto fittizio ed il gioco è fatto!

E se noi non caricassimo i dati nel costruttore del ViewModel? Ad esempio le proprietà potrebbero essere valorizzate quando ci arriva un messaggio dal MessageBroker ( IMediator ).
Marlon ci mette a disposizione l’interfaccia IDesignTimeAware, che dovrà essere implementata dal ViewModel

image

ed all’interno del metodo DesignTimeInitialization valorizzeremo le proprietà.

image

DesignTimeInitialization verrà chiamato a DesignTime!

In questo post abbiamo visto soltanto le basi di questo framework e le funzionalità che offre sono veramente sorprendenti!

Per il 15 ottobre XeDotNet ha organizzato un Virtual Meeting dove vedremo MEFedMVVM, come creare un Plugin Manager con MEF e molto probabilmente mostrerò una piccola demo su com’è possibile caricare plugins tramite MEF in un AppDomain secondario!

Di seguito riporto il link al progetto MEFedMVVM su codeplex ed alcuni articoli utili :)

http://mefedmvvm.codeplex.com/

http://marlongrech.wordpress.com/2010/05/23/mefedmvvm-v1-0-explained/
http://marlongrech.wordpress.com/2010/05/09/mefedmvvm-changes-from-cool-to-cooler/
http://marlongrech.wordpress.com/2010/05/26/mefedmvvm-testability/
http://marlongrech.wordpress.com/2010/04/24/an-introduction-to-mefedmvvm-part-1/
http://marlongrech.wordpress.com/2010/04/25/leveraging-mefedmvvm-exportviewmodel-mefedmvvm-part-2/
http://marlongrech.wordpress.com/2010/04/25/icontextaware-services-to-bridge-the-gap-between-the-view-and-the-viewmodel-mefedmvvm-part-3/
http://marlongrech.wordpress.com/2010/04/27/how-does-mefedmvvm-compose-the-catalogs-and-how-can-i-override-the-behavior-mefedmvvm-part-4/