插件式程序开发
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
5/14/2016
补充一
更新:DirectoryCatalog 只能加载一个文件夹,且不能递归加载子孙目录,如果希望加载子目录, 需要自己写代码添加:
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\plugin\"; foreach (string di in Directory.EnumerateDirectories(path)) { catalog.Catalogs.Add(new DirectoryCatalog(di)); }
安装接受者
有了协议之后,就需要给应用程序安一个接 受者。让这个应用程序可以通过接受者来获 取第三方扩展。MEF 提供了 [Import] 和 [ImportMany] 两种 attribute。 区别就是 Import 只能接受符合协议的一个扩展,而 ImportMany 可以接受多个,并把多个扩展 放入集合中。
5/14/2016
MEF 的关键概念
Contract 协议。要想使盒子能接受积木(比如,圆柱体只能放入圆形的接口中),那这些 积木必须符合一定的形状。而这些形状就相当于是应用程序和第三方扩展之间的 一个协议。
5/14/2016
MEF 的关键概念
Compose 组合(动词),即将多个符合协议要求的部件组合在一起,构成一个功能丰富的 应用程序。就好比是将不同形状的积木,按照接口的形状组合在一起。
5/14/2016
运行界面
5/14/2016
MEF 和 提起插件式 异同
MEF:工程内部添加对接口的引用
提起插件式:主程序不添加对接口的引用 不需要Import,Export标记
都自动遍历程序启动目录下 plugin目录中符合协议的插件dll 5/14/2016
THE END
5/14/2016
符合协议的产物
这个产物的生产过程其实就是实现 接口的过程,唯一的区别是我们要 为这个实现打上个标签,从而告诉 我们的组合引擎这个东西是给接受 者的。MEF 提供了 Export 来暗示 这是一个可以提供给接受者的产物 。
注:添加 System.ComponentModel.Composition 程序集到项目中。
}
5/14/2016
提起插件式 使用插件
try{ if (this.listbox1.SelectedIndex == -1) return; object selObj = this.plugins[this.listbox1.SelectedIndex]; Type t = selObj.GetType(); MethodInfo OnShowDlg = t.GetMethod("OnShowDlg"); if (OnShowDlg != null){OnShowDlg.Invoke(selObj, null);} MethodInfo OnShowInfo = t.GetMethod("OnShowInfo"); if (OnShowInfo != null){ object returnValue = OnShowInfo.Invoke(selObj, null); this.lable1.Content = returnValue.ToString(); } } catch { }
this.panel1.Controls.Add(btn);
} }
5/14/2016
示例代码
符合协议的产物 MyPlugin namespace PluginInstance{ [Export(typeof(IPlugin))] public class MyPlugin:IPlugin{ public string Text{ get{return "This is a demo";} } public void Do(){MessageBox.Show(Text);}
5/14/2016
补充二
更新:DirectoryCatalog 默认只加载 *.dll 类型文件,如果希望加载其它类型文件,可以这样:
////从exe中获取Parts catalog.Catalogs.Add(new DirectoryCatalog(path, "*.exe")); ////从dll中获取Parts catalog.Catalogs.Add(new DirectoryCatalog(path, "*.dll"));
}
}
5/14/2016
示例代码
发动引擎
private CompositionContainer _container; private void Init(){ var catalog = new AggregateCatalog(); string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\plugin\"; catalog.Catalogs.Add(new DirectoryCatalog(path, "*.dll")); _container = new CompositionContainer(catalog); try {this._container.ComposeParts(this);} catch (CompositionException compositionException){ Console.WriteLine(compositionException.ToString());} }
宿主
宿主视图
宿主 适配器
协 定
插件 适配器wk.baidu.com
插件视图
插件
5/14/2016
MEF 拓展可扩展性框架
(适用)
5/14/2016
MEF 拓展可扩展性框架
MEF(Managed Extensibility Framework),是微软推出的一款用于搭建可扩展 应用程序的框架,起初是独立于 .Net 发布的,后来集成到了 .Net 4.0 中。使用 该框架可以非常轻松地扩展一个已发布的应用程序的功能,连 Visual Studio IDE 中的代码编辑器窗口也采用了MEF的思想,因此大大方便了开发人员对编辑 器的扩展。 MEF 可用在任何使用 .NET Framework 的地方。可以在客户端应用程序中使用 MEF(无论应用程序使用的是 Windows 窗体、WPF,还是任何其他技术),也
主程序不添加对接口的引用,也不应该在客户端实例化插件对象,因为插件开发
的初衷是为了以后更新的时候不更改主程序,只提供对应的dll 下载,就可以直 接使用了,以前的接口都定义好了,新的实现类也就是不可预料的,因此不在主 程序实例化实现接口的类。
5/14/2016
提起插件式 协议接口IMsg
namespace IMsg { public interface IMsgPlug { void OnShowDlg(); } }
可以在使用 ASP.NET 的服务器应用程序中使用 MEF。
5/14/2016
MEF 的关键概念
Import 导入,这里建议作为一个名词来理解,即一个接受者,它可以接受外来的东西。 就好比是下图中的盒子,它可以接受其它积木。
5/14/2016
MEF 的关键概念
Export 导出,同样建议以一个名词来理解,即一个第三方的产物。它就像上图中不同颜 色的积木,这些积木不属于这个盒子,但是能被放入盒子中,来丰富盒子的功能。
5/14/2016
运行界面
5/14/2016
MEF DEMO程序总结
在工程内部添加对接口的引用,插件dll或者插件exe按照协议约定方式进行实现
5/14/2016
提起插件式
(适用)
5/14/2016
提起插件式
这样的主程序不需要改动。需要插件时,拿来就能用,插件更新时,也只需更新 这个插件即可。 需要判断的只是插件dll是否由预定义的插件接口实现,如果有则认为该类适配于 主程序(是主程序的插件)
}
5/14/2016
示例代码
安装接收器 [ImportMany] public IEnumerable<IPlugin> plugins; private void Form1_Load(object sender, EventArgs e){ foreach (IPlugin plugin in plugins){ Button btn = new Button { Text=plugin.Text}; btn.Click += (s, arg) => { plugin.Do();}; btn.Width = 100;
5/14/2016
用 MEF 实现一个最简单的可扩展应用程序
发动引擎
代码会自动去发现扩展,然后加入到应 用程序中来。要做的只是把新扩展的程 序集放入 执行目录下的plugin 目录中 就可以了
5/14/2016
示例代码
协议接口IPlugin namespace Core { public interface IPlugin { string Text { get; } void Do(); }
插件式程序开发
5/14/2016
目录
1 2 3 MAF 托管插件框架 MEF 拓展可扩展性框架 提起插件式
5/14/2016
MAF 托管插件框架
(不适用)
5/14/2016
MAF 托管插件框架
MAF是一个复杂的框架,并且即使是对于简单的应用程序,设置插件管道也很繁 琐。它比MEF复杂,需要配置很多元素。但它也有些优点:1.宿主程序和插件程 序可以进行隔离,以此降低运行插件所带来的风险;2。MAF的设计是基于7个程 序集组成的管道,这些管道部分可以单独更换。
5/14/2016
它是如何工作的?
Plugin dir MEF 会动态查找用户所指定的目录,如果发现该目录中的程序集满足协议要求, 就会启动自身的组合引擎,然后根据不同的协议约定把这些扩展导入到应用程序 内部。
5/14/2016
用 MEF 实现一个最简单的可扩展应用程序
协议
这个和普通定义接口没什么两样 。
5/14/2016
提起插件式 符合协议产物 MyPlugin
... public void OnShowDlg(){ InitializeComponent(); this.ShowDialog(); } ...
5/14/2016
提起插件式 加载插件
string[] files = Directory.GetFiles(Directory.GetCurrentDirectory() + @"\Plugins"); foreach (string file in files){ if (file.ToUpper().EndsWith(".DLL")){ try{ Assembly ab = Assembly.LoadFrom(file); //载入dll Type[] types = ab.GetTypes(); foreach (Type t in types){ if (t.GetInterface("IMsgPlug") != null){ plugins.Add(ab.CreateInstance(t.FullName)); listbox1.Items.Add(t.FullName);}}} catch (Exception ex) {MessageBox.Show(ex.Message);}