Search code examples
c#mvvmmef

Import not work when using MEF in WPF MVVM


I want to do a test of MEF on WPF. I use a project as interfaces:

// Project name MEFWpfTest.Interfaces
public interface IAppViewModel
{
    string Name { get; set; }
}

then create a new project to implement this interface:

// Project name MEFWpfTest.ViewModels
[Export("AppViewModel")]
public class AppViewModel : IAppViewModel
{
    public string Name { get; set; }
}

in App.xaml.cs, WPF project, I try to compose parts in MEF:

// Project name MEFWpfTest
public partial class App : Application
{
    private void Application_Startup(object sender, StartupEventArgs e)
    {
        var aggregateCatalog = new AggregateCatalog();
        Assembly assembly = Assembly.GetExecutingAssembly();
        aggregateCatalog.Catalogs.Add(new AssemblyCatalog(assembly));

        var directoryPath = Path.GetDirectoryName(assembly.Location);

        if (directoryPath != null)
        {
            aggregateCatalog.Catalogs.Add(new DirectoryCatalog(directoryPath, $"MEFWpfTest.*.dll"));

        }

        CompositionContainer Container = new CompositionContainer(aggregateCatalog);
        Container.ComposeParts(this);

        MainWindow w = new MainWindow();
        w.Show();
    }
}

then in MainWindow.xaml.cs, I use a IAppViewModel to Import:

// Project name MEFWpfTest
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    [Import("AppViewModel")]
    public Interfaces.IAppViewModel AppVM { get; set; }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    { // I set a break point here.

    }
}

when I run this application, I've found that AppVM is null. It's fine when I do the same thing in One assembly. MEFWpfTest already referenced MEFWpfTest.Interfaces and MEFWpfTest.ViewModels.

where I do wrong?


Solution

  • Compose parts on its constructor:

    public MainWindow()
    {
        InitializeComponent();
        Container.ComposeParts(this); // get container somehow
    }
    

    Note that importing property/field owner class automatically imports its properties/fields without explicit ComposeParts(). If AppViewModel has [Import] properties/fields, they are set automatically. You don't need to call ComposeParts(this) in the constructor of AppViewModel. ComposePart() cascades importing of the classes.