MongoDB管理工具的插件系统
MongoDB管理工具 MongoCola的开发已经进入第三个年头了。
官方对于C#驱动的投入不够导致了很多东西都必须自己实现,但是不管怎么样,工具现在已经很强大了。
最近准备着手插件系统的开发,简单的插件系统,其实代码量非常的少。
1.插件基类
插件系统需要一个插件基类的支持,这个基类,规定了一个插件所包含的固有字段,例如插件名称,插件说明,插件作者等等。
同时,还定义了主方法的名称,毕竟插件系统肯定要使用反射来完成,所以很多东西必须要统一起来。
1 using System; 2 3 namespace MagicMongoDBTool.Common 4 { 5 public abstract class PlugBase 6 { 7 /// <summary> 8 /// 路径阶层[考虑到以后可能阶层会变换] 9 /// </summary> 10 public enum PathLv : int 11 { 12 /// <summary> 13 /// 连接/服务器 14 /// </summary> 15 ConnectionLV = 0, 16 /// <summary> 17 /// 具体的实例 18 /// </summary> 19 InstanceLV = 1, 20 /// <summary> 21 /// 数据库 22 /// </summary> 23 DatabaseLV = 2, 24 /// <summary> 25 /// 数据集 26 /// </summary> 27 CollectionLV = 3, 28 /// <summary> 29 /// 数据文档 30 /// </summary> 31 DocumentLV = 4, 32 /// <summary> 33 /// 杂项 34 /// </summary> 35 Misc = 9 36 } 37 /// <summary> 38 /// 插件菜单表示名称 39 /// </summary> 40 public string PlugName = String.Empty; 41 /// <summary> 42 /// 插件功能简述 43 /// </summary> 44 public string PlugFunction = String.Empty; 45 /// <summary> 46 /// 处理对象 47 /// </summary> 48 public dynamic PlugObj; 49 /// <summary> 50 /// 对象层次 51 /// </summary> 52 public PathLv RunLv = PathLv.ConnectionLV; 53 /// <summary> 54 /// 运行 55 /// </summary> 56 /// <returns></returns> 57 public abstract int Run(); 58 } 59 }
Run是个抽象方法,既然是抽象方法,继承这个类的插件都必须实现这个方法。Run也是以后工具调用插件功能的入口函数。
这个基类,可以以源代码的形式添加到插件的工程里面,当然,也可以做成一个DLL,让插件的工程引用。我现在讲它做成了DLL。
2.工具如何发现插件
做法也很简单,所有的插件的DLL统一放在指定目录中,然后使用强大的反射,获取插件的基本情报,放在字典里面
using MagicMongoDBTool.Common; using System; using System.Collections.Generic; using System.Reflection; using System.Windows.Forms; namespace MagicMongoDBTool.Module { public class PlugIn { public static Dictionary<String, PlugBase> PlugInList = new Dictionary<string, PlugBase>(); /// <summary> /// 加载到菜单项目 /// </summary> public static void LoadPlugIn() { ///注意 ///必须将Common.DLL放在Bin下面! foreach (var mFile in System.IO.Directory.GetFiles(Application.StartupPath + @"\PlugIn\","*.dll")) { try { Assembly mAssem = Assembly.LoadFile(mFile); String FileName = mFile.Replace(Application.StartupPath + @"\PlugIn\", String.Empty); if (FileName == "MagicMongoDBTool.Common.dll") continue; String TypeName = FileName.Substring(0, FileName.Length - 4); Type mType = mAssem.GetType(TypeName + "." + TypeName); ConstructorInfo ConstructorInfo = mType.GetConstructor(new System.Type[] {}); PlugBase mPlug = (PlugBase)ConstructorInfo.Invoke(new object[] { }); PlugInList.Add(TypeName, mPlug); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } } } } }
这里需要注意一个问题,由于插件使用了插件基类PlugBase,PlugBase是放在一个独立的DLL中的,所以,请将这个DLL放在可执行文件的同一目录下面。
理由是,反射执行的时候,需要访问PlugBase基类的构造。(可能是这样吧)
3.将插件展示在菜单里面
PlugIn.LoadPlugIn(); foreach (var plugin in PlugIn.PlugInList) { ToolStripItem menu = new ToolStripMenuItem(plugin.Value.PlugName); menu.ToolTipText = plugin.Value.PlugFunction; menu.Tag = plugin.Key; menu.Click += new EventHandler( (x, y) => { RunPlugIn(plugin.Key); } ); this.plugInToolStripMenuItem.DropDownItems.Add(menu); }
就是一个很简单的动态创建菜单
4.运行插件
/// <summary> /// 运行插件 /// </summary> /// <param name="PlugInKeyCode"></param> private void RunPlugIn(string PlugInKeyCode) { System.Reflection.Assembly mAssem = Assembly.LoadFile(Application.StartupPath + @"\PlugIn\" + PlugInKeyCode + ".dll"); String TypeName = PlugInKeyCode; Type mType = mAssem.GetType(TypeName + "." + TypeName); ConstructorInfo ConstructorInfo = mType.GetConstructor(new System.Type[] { }); PlugBase mPlug = (PlugBase)ConstructorInfo.Invoke(new object[] { }); switch (PlugIn.PlugInList[PlugInKeyCode].RunLv) { case MagicMongoDBTool.Common.PlugBase.PathLv.ConnectionLV: mPlug.PlugObj = SystemManager.GetCurrentServer(); break; case MagicMongoDBTool.Common.PlugBase.PathLv.InstanceLV: mPlug.PlugObj = SystemManager.GetCurrentServer(); break; case MagicMongoDBTool.Common.PlugBase.PathLv.DatabaseLV: mPlug.PlugObj = SystemManager.GetCurrentDataBase(); break; case MagicMongoDBTool.Common.PlugBase.PathLv.CollectionLV: mPlug.PlugObj = SystemManager.GetCurrentCollection(); break; case MagicMongoDBTool.Common.PlugBase.PathLv.DocumentLV: break; default: break; } mPlug.Run(); }
采用反射运行插件,没有什么技术含量。
5.简单的做了一个Sample,学过MongoDB的,自然看得懂了
using MagicMongoDBTool.Common; using MongoDB.Driver; using System.Windows.Forms; namespace ExportToExcel { public class ExportToExcel:PlugBase { /// <summary> /// 内部变量 /// </summary> MongoCollection ProcessCollection; /// <summary> /// 初始化设定 /// </summary> public ExportToExcel() { base.RunLv = PathLv.CollectionLV; base.PlugName = "导出到Excel工具"; base.PlugFunction = "将数据集导出到Excel"; } /// <summary> /// 运行 /// </summary> /// <returns></returns> public override int Run() { ProcessCollection = base.PlugObj; MessageBox.Show(ProcessCollection.Name); return 0; } } }
园子里面使用MongoDB的朋友不是很多,我想找个朋友一起来继续开发这个工具。或者找人帮我开发一些插件。
中国的开源项目,期初很热闹,但是过一段时间,就冷清了。我想找的开发伙伴,希望能耐得住寂寞,能够长期保持开发热情。
人不需要太多,1个2个就可以了。
工具官方网址
GitHub
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。