也来学学插件式开发续-利用MEF

前面一个博客:也来学学插件式开发中很多朋友留言说可以用MEF来实现。于是我就试着用MEF实现了一下。

步骤和上一篇差不多,只是加载插件的方式有所不同。这只是一个自己的示例程序,肯定有很多不足之处,欢迎拍砖。

MEF如何工作?

MEF主要是通过ImportExport特性来定义导入与导出部件。程序在运行的时候会将具有相同接口的导出的实例化,赋给导入。

MEF程序设计指南一:在应用程序中宿主MEF这篇文章有一个简单的MEF例子,大家可以参考一下。

所以,在这里,插件就是导出,我们在程序中要定义具有和插件相同接口的导入。

但是这里有一个问题,一般的导入与导出是一对一的,但我们的工具箱中和插件的关系明显是一对多的怎么办?

没问题,MEF对于这种情况可以将导入声明为ImportMany,这样就支持一个导入对应多个导出了。

关于ImportMany可参见:http://msdn.microsoft.com/en-us/library/dd460648.aspx#further_imports_and_importmany

因此这里,我用ImportMany来定义一个集合来保存插件:

        [ImportMany]
        public IEnumerable<Iplugin> plugins;

如何让MEF发现插件?

我们用反射的时候是将插件放置在一个固定的目录中,然后再去扫描这个目录来发现插件,在MEF中如何来发现插件呢?

MEF提供三种方式发现部件:

  1. AssemblyCatalog 在当前程序集发现部件。
  2. DirectoryCatalog 在指定的目录发现部件。
  3. DeploymentCatalog 在指定的XAP文件中发现部件(用于silverlight)

可以看到,我们也可以将插件放在统一的目录让MEF去检索发现。

使用MEF

使用MEF的时候,首先要初始化MEF的组合容器对象:CompositionContainer,所以在窗体加载的时候要做好初始化工作。

        public ToolBox()
        {
            InitializeComponent();
            Init();
        }
        private CompositionContainer _container;

        private void Init()
        {
            //An aggregate catalog that combines multiple catalogs
            var catalog = new AggregateCatalog();
            //设置目录
            catalog.Catalogs.Add(new DirectoryCatalog(Application.StartupPath + "\\plugin\\"));

            //Create the CompositionContainer with the parts in the catalog
            _container = new CompositionContainer(catalog);

            //Fill the imports of this object
            try
            {
                this._container.ComposeParts(this);
            }
            catch (CompositionException compositionException)
            {
                Console.WriteLine(compositionException.ToString());
            }
        }

接着就是发现插件后的显示工作了:

        private void ToolBox_Load(object sender, EventArgs e)
        {
            InitPlugin();
        }

        [ImportMany]
        public IEnumerable<Iplugin> plugins;


        public void InitPlugin()
        {
            foreach (Iplugin plugin in plugins)
            {
                InitModule(plugin);
            }
        }

增加插件

我们来新增一个插件试试。新建一个类库项目,再增加一个Window窗体,拉一个PictureBox,显示一张图片。主要的工作是我们要定义导出:Export

   [Export(typeof(PluginMain.Interface.Iplugin))]
    public class App:PluginMain.Interface.Iplugin
    {
        public System.Windows.Forms.Form MainForm
        {
            get { return new Picture(); }
        }

        public System.Drawing.Image ModulePicture
        {
            get { return null; }
        }
    }

将生成的.DLL放在plugin目录中。生成后效果如图:

 示例代码下载:点我

 

参考资料:【.Net平台下插件开发】-MEF与MAF初步调研

             《MEF程序设计指南》博文汇总

             Managed Extensibility Framework (MEF)

posted @ 2013-02-26 19:57  Gyoung  阅读(6359)  评论(8编辑  收藏  举报