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
https://github.com/magicdict/MagicMongoDBTool
