Eravamo rimasti con l’avere un qualcosa di semplice ma funzionante ed in questa parte vedremo piu’ in dettaglio come utilizzare gli Export e gli Import, a cosa serve la classe Lazy<T> e l’attributo PartCreationPolicy.
Exports
Finora abbiamo visto che una ComposablePart puo’ esportare properties, fields oppure se stessa (come nel caso del MainViewModel).
Se invece avessimo l’esigenza di esportare un metodo, MEF lo vedrebbe come un delegate per cui è necessario specificare il delegate che stiamo esportando (in questo caso un Action<string>)
e di conseguenza l’import dovrà avere lo stesso contratto
Imports
Se volessimo passare le dipendenze tramite costruttore come fa un IoC container? Niente di piu’ facile :) MEF ci offre l’attributo ImportingConstructor
NB: per discussioni riguardo all'uso di MEF come IoC container date un’occhiata a questi post di Glenn Block
http://codebetter.com/blogs/glenn.block/archive/2009/08/16/should-i-use-mef-for-my-general-ioc-needs.aspx
http://codebetter.com/blogs/glenn.block/archive/2009/10/31/should-i-use-mef-with-an-ioc-container.aspx
Una chicca offerta da MEF è l’attributo ImportMany che ci permette di importare piu’ plugin (nel nostro caso) con lo stesso contratto
modificando leggermente la view ed aggiungendo qualche plugin all’interno del progetto otteniamo un risultato di questo tipo
Ma come facciamo a sapere se gli imports di una nostra classe sono stati eseguiti correttamente? In questo caso ci viene incontro l’interfaccia IPartImportsSatisfiedNotification con il suo unico metodo OnImportsSatisfied che verrà chiamato quando tutti gli imports che possono essere soddisfatti verranno eseguiti.
Lazy:
Quando il container inizia a fare il suo sporco lavoro (cioè comporre le varie parti) e trova un Import, questo Import comporterà la creazione di una o piu’ istanze della parte che lo soddisfa. Questo potrebbe essere un fattore da considerare nel caso della creazione di grossi grafi di oggetti. Proprio per questo all’interno di MEF è presente la classe Lazy<T> che si occuperà di creare l’istanza della classe specificata al primo utilizzo.
La prima volta che si andrà ad utilizzare la proprietà Plugin MEF creerà l’istanza del relativo export e potremo accedervi semplicemente scrivendo Plugin.Value (la proprietà Value ritornerà sempre la stessa istanza).
Quando il container cerca di comporre tutto “l’ambaradan” e non trova un export che per ogni import definito lancerà un’eccezione, ma per evitare tutto ciò è possibile settare la proprietà AllowDefault della classe ImportAttribute a true. In tal modo il container darà all’import non soddisfatto il valore di default.
Ora mettiamo il caso che scriviamo un qualcosa del genere…o meglio creiamo due o piu’ proprietà che hanno lo stesso contratto. La domanda che sorge spontanea è: il container come reagirà? Creerà due istanze diverse oppure Plugin e Plugin2 punteranno alla stessa istanza?
Debuggando il tutto si puo’ notare che entrambe le proprietà puntano alla stessa istanza (hanno Object ID uguale). E se volessimo avere istanze diverse?
E’ sufficiente decorare l’export con l’attributo PartCreationPolicy e passargli CreationPolicy.NonShared
Nel prossimo post vedremo i Catalog messi a disposizione da MEF (Preview 8) e l’implementazione di un catalogo personalizzato.
Stay tuned…
posted @ domenica 7 febbraio 2010 14:36