Fork me on GitHub

Prism6下的MEF:第一个Hello World

最近看书比较多,正好对过去几年的软件开发做个总结。写这个的初衷只是为了简单的做一些记录。

前言

复杂的应用程序总是面临很多的页面之间的数据交互,怎样创建松耦合的程序一直是多数工程师所思考的问题。诸如依赖注入,PubSub模式,MVVM等概念,都致力于帮助我们创建更加松耦合易于维护的程序,也有不少框架实现了这些功能,Prism就是其中一个。
Prism是微软的实践和模式小组写的一套框架,包含了常用的依赖注入方式(Autofac,Mef,Ninject,StructureMap,Unity),MVVM,数据校验,基于PubSub的消息模型,导航,插件管理等等功能,能够帮助我们创建伸缩性好,耦合度低的程序。下面我们开始尝试从一个普通的WPF程序开始,将它改造成一个使用Prism框架的程序。

开发环境

Windows 10 10586
Visual Studio 2015
.Net Framework 4.6.1
Prism 6

新建PrismSample项目

因为希望能够进行插件式的开发,所以IoC容器选择了MEF。新建一个WPF项目,命名为PrismSample。然后我们需要从nuget导入三个包:
Image

我们先将Prism.Core,Prism.Mef,Prism.MVVM添加进来。添加完之后,我们需要将我们的MainWindow删除掉,因为我们希望实现自己的主页面。当然,在App.xaml文件中也要做修改:

<Application x:Class="PrismSample.App"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:PrismSample">
    <Application.Resources>
        
    </Application.Resources>
</Application>

这时候,我们的项目是无法正常启动的。接下来我们要新建一个Shell页面,作为我们的主页面。

新建PrismSample.Infrastructure.Abstract

新建一个类库项目,将其命名为PrismSample.Infrastructure.Abstract,并建立如下结构的文件:
Image

为了创建IViewModel接口和ViewModelBase的抽象类,我们需要先从nuget中引入Prism.Mvvm。当我们添加完后,实现文件内容如下:

namespace PrismSample.Infrastructure.Abstract.Presentation.Interface
{
    public interface IViewModel
    {
        IView View { get; }
    }
}


using Microsoft.Practices.Prism.Mvvm;
using PrismSample.Infrastructure.Abstract.Presentation.Interface;

namespace PrismSample.Infrastructure.Abstract.Presentation.AbstractClass
{
    public abstract class ViewModelBase : BindableBase, IViewModel
    {
        public IView View { get; protected set; }
    }
}

在PrismSample中实现内容

新建Shell页面

添加页面Shell:

<Window x:Class="PrismSample.Shell"
    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:PrismSample"
    mc:Ignorable="d"
    Title="Shell" Height="300" Width="300">
    <Grid>
        <TextBlock Text="{Binding Text}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>
</Window>


using Microsoft.Practices.Prism.Mvvm;
using System.ComponentModel.Composition;
using System.Windows;

namespace PrismSample
{
    [Export("ShellView", typeof(IView))]
    public partial class Shell : Window, IView
    {
        public Shell()
        {
            InitializeComponent();
        }
    }
}

新建Shell的ViewModel

using PrismSample.Infrastructure.Abstract.Presentation.Interface;
using Microsoft.Practices.Prism.Mvvm;
using System.ComponentModel.Composition;
using PrismSample.Infrastructure.Abstract.Presentation.AbstractClass;

namespace PrismSample
{
    [Export("ShellViewModel",typeof(IViewModel))]
    public class ShellViewModel : ViewModelBase
    {
        private string _text;

        public string Text
        {
            get { return _text; }
            set { SetProperty(ref _text, value); }
        }

        [ImportingConstructor]
        public ShellViewModel([Import("ShellView", typeof(IView))]  IView view)
        {
            this.View = view;
            this._text = "Hello World";
            this.View.DataContext = this;
        }
    }
}

新建Bootstrapper类

using Prism.Mef;
using PrismSample.Infrastructure.Abstract.Presentation.Interface;
using System.ComponentModel.Composition.Hosting;
using System.Windows;

namespace PrismSample
{
    public class Bootstrapper : MefBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
            IViewModel shellViewModel = this.Container.GetExportedValue<IViewModel>("ShellViewModel");      
            return shellViewModel.View as DependencyObject;
        }

        protected override void InitializeShell()
        {
            Application.Current.MainWindow = (Shell)this.Shell;
            Application.Current.MainWindow.Show();
        }

        protected override void ConfigureAggregateCatalog()
        {
            base.ConfigureAggregateCatalog();

            //加载自己
            this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(this.GetType().Assembly));
        }
    }
}

修改App.xaml.cs文件

using System.Windows;

namespace PrismSample
{
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            Bootstrapper bootstrapper = new Bootstrapper();
            bootstrapper.Run();
        }
    }
}

最后的文件结构和运行结果

Image
Image

小结

本篇通过一个简单的应用建立了一个基于Prism的包含Ioc和Mvvvm的小程序,虽然是个小程序,但包含了Prism的精髓--组合。
源码下载

参考信息

Silverlight中利用MEF进行模块注入时注入错误问题分析
【翻译】WPF应用程序模块化开发快速入门(使用Prism框架)【上】

posted @ 2016-07-14 14:55  tianjyan  阅读(2666)  评论(8编辑  收藏  举报