How can I leverage MEF in my MVVM application? [cl

2019-02-11 08:47发布

Can anybody give me a simple wpf application using mef and following mvvm pattern. I have looked a lot on the internet but i found very few examples and those example are very complex to understand. some examples are wpf, mef but dont follow mvvm pattern.

here is what i am trying to do.

There will a main wpf application. This will load all the modules (plugins) and show it to user. A module will contain 2 or 3 pages with next back buttons (used for navigation). Now when in main application i select a module, module opens or what you can say it replaces current window and on button navigation it changes views of the module.

Main Window -> Module 1 -> Page 1

                       Page 2

                       Page 3

           Module 2 -> Page 1

                       Page 2

                       Page 3

So it look clean now. Module 1 is a seperate project, module 2 is a seperate project. main window reads modules from dll and show them. clicking a module will go through its pages.

标签: wpf mvvm mef
2条回答
贪生不怕死
2楼-- · 2019-02-11 09:28

i did 2 projects these days which do that what you want. what i have done is to set up a main project which does nothing more than collecting the modules via MEF and handle the selection of the module. you also need a component project where you set up the interfaces and export attributes.

here some sample code pieces:

MainProject app.xaml.cs

public partial class App : Application
{
    [ImportMany]
    private IEnumerable<Lazy<IComponent, IComponentMetadata>> _components;
    private CompositionContainer _mefcontainer;

    protected override void OnStartup(StartupEventArgs e)
    {
        ShutdownMode = ShutdownMode.OnExplicitShutdown;

        //i do login stuff here

        //i use task.factory here and dynamic splashscreen here

        this.MefContainer.ComposeParts(rahmen, this);

        foreach (var component in _components)
        {
            //check metadata and fill modules collection
        }

        //add modules collection to mainwindowviewmodel

         ShutdownMode = ShutdownMode.OnMainWindowClose;

         this.MainWindow.Show();

    }
}

Component.dll

public interface IComponent//Marker interface
{
    bool HasChanges { get; }
}

public interface IComponentMetadata
{
    string Displayname { get; }

    int SortIndex { get; }

    string ImagePath { get; }

    string IconPath { get; }
}

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ComponentExportAttribute : ExportAttribute, IComponentMetadata
{
    private const string DEFAULTICON = "pack://application:,,,/MyComponent;Component/Images/Default.png";


    public ComponentExportAttribute(string displayname, int sortindex): base(typeof(IComponent))
    {
        this.Displayname = displayname;
        this.SortIndex = sortindex;

        this.ImagePath = DEFAULTICON;
        this.IconPath = DEFAULTICON;
    }


    public ComponentExportAttribute(string displayname, int sortindex, string imagepath, string iconpath): base(typeof(IComponent))
    {
        this.Displayname = displayname;
        this.SortIndex = sortindex;

        this.ImagePath = String.IsNullOrWhiteSpace(imagepath) ? DEFAULTICON : imagepath;
        this.IconPath = String.IsNullOrWhiteSpace(iconpath) ? DEFAULTICON : iconpath;
    }

    #region Implementation of IComponentMetadata

    public string Displayname { get; private set; }

    public int SortIndex { get; private set; }

    public string ImagePath { get; private set; }

    public string IconPath { get; private set; }

    #endregion
}

Modul example

[ComponentExport("Test1",  150
    , "pack://application:,,,/TestProject;Component/Test/Logo1.png"
    , "pack://application:,,,/TestProject;Component/Test/Icon1.png")]
public partial class Test1MainWindow : UserControl, IComponent
{
    [ImportingConstructor]//if you want to do DI
    public Test1MainWindow ()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    #region Implementation of IComponent

    public bool HasChanges
    {
        get { return false; }
    }

    #endregion
}

or viewmodel export --> (if you do this you have to export a datatemplate to the mainapp, i can show this if you want)

[ComponentExport("Test2", 500 
    , "pack://application:,,,/TestProject;Component/Test/Logo2.png"
    , "pack://application:,,,/TestProject;Component/Test/Icon2.png")]
public class Test2: INPCBase, IComponent
{

    [ImportingConstructor]
    public Test2()
    {
    }

    #region Implementation of IKabuComponent

    public bool HasChanges
    {
        get { return false; }
    }

    #endregion
}
查看更多
走好不送
3楼-- · 2019-02-11 09:43

Microsoft has a few reference implementations lying around that you may find useful. they are a good showcase of MVVM / MEF and WPF. here's the very first blog about the StockTrader RI implementation with the download link pointing here. the Microsoft overview of the StockTrader RI and MVVM RI implementations are here, and here's the StockTrader RI implementation specifically. hth.

查看更多
登录 后发表回答