Ho parlato di MEF (Managed Extensibility Framework) parecchio tempo fa, ora che il framework è ben definito è evidente che se dovete sviluppare un applicazione ‘dinamica’ (o a plug-in se preferite) MEF è sicuramente la tecnologia da utilizzare.
Ovviamente se l’applicazione è WPF o Silverlight l’accoppiare MEF e Model-View-ViewModel è d’obbligo, ecco quindi un semplice esempio di M-V-VM basato sul principio di composizione di MEF.
Data Provider
public interface IProvider
{
string GetName();
}
[Export(typeof(IProvider))]
public class MyProvider:IProvider
{
public string GetName()
{
return "Provider generated";
}
}
ViewModel
[Export]
public class MyVm : ViewModelBase
{
public MyVm()
{
this.Name = "Design time generated";
}
[ImportingConstructor]
public MyVm(IProvider provider)
{
this.Name = provider.GetName();
}
public string Name { get; set; }
}
A questo punto dobbiamo accoppiare il ViewModel alla relativa View, quale occasione migliore per usare -di nuovo- MEF?
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
PartInitializer.SatisfyImports(this);
}
[Import]
public MyVm ViewModel
{
get { return (MyVm)this.DataContext; }
set {this.DataContext = value; }
}
}
View:
<UserControl x:Class="Blendability.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Blendability"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Text="{Binding Name}" />
</Grid>
</UserControl>
Premendo F5 grazie a MEF i vari elementi verranno letteralmente composti e quindi vedremo apparire “Provider generated” nella pagina web.
Rimane un problema fondamentale: visto che PartInitializer.SatisfyImports ovvero il metodo che informa MEF di valorizzare la proprietà ViewModel della View scatenando di conseguenza tutta relativa composizione non funziona a design time (quindi non possiamo usare l’approccio tradizionale) come otteniamo la Blendability?
Fortunatamente la risposta è semplice: usare lo stesso metodo usato da Blend, ovvero fornire un DataContext da utilizzare esclusivamente a design time, come? usando il namespace ‘d:’.
Semplicemente modificando lo xaml della View in questo modo:
<Grid x:Name="LayoutRoot" Background="White"
d:DataContext="{d:DesignInstance local:MyVm, IsDesignTimeCreatable=true}">
<TextBlock Text="{Binding Name}" />
</Grid>
ottengo la creazione di un istanza a design time la quale usa il parameterless constructor all’interno del quale creo i dati fittizi da usare durante la fase di design.
Sicuramente MEF è destinato a diventare parte integrante delle applicazioni WPF/Silverlight e, visto che M-V-VM già lo è presumo che nei prossimi mesi ci sarà un grosso interesse e di conseguenza parecchi posts relativamente a come accoppiare i due nel migliore modo possibile.
Stay tuned.