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.