這是本人畢業設計的項目,一直想將其整理成文,可一不小心4年就過去了(這個時間又可以讀個大學了)。現在給自己定一個目標,一個月時間裡將項目的所有關鍵點都整理出來。不然真怕一眨眼又一個4年過去了,而代碼依然躺在硬盤裡。
項目取名MathAssist,使用vs2008。分成四個子項目:
其主程序可以從插件中掃描可用的命令,也可以顯示插件中可用的窗體。如下是主程序界面,其加載了兩個插件:“superCalculator”和“命令證明”。它們分別提供命令cal prove。
點擊菜單項"插件"的子菜單後可以分別打開兩個插件中實現的窗口。如下圖
分別實現了大數計算和邏輯命題的證明。
在這篇前言中就先只介紹插件機制的實現吧,大數計算和邏輯命題的證明就留給後面的系列。
在MathAssistLibrary項目中只定義了兩個接口: ICommand, IForm,分別用於提供命令行功能和窗口功能。
1 /// <summary>命令接口</summary> 2 public interface ICommand 3 { 4 /// <summary>命令名稱</summary> 5 string Name { get; } 6 7 /// <summary>執行命令</summary> 8 /// <param name="cmd">命令參數</param> 9 /// <returns>返回的結果</returns> 10 string Excute( string cmd ); 11 12 /// <summary>對命令的使用作相應的說明</summary> 13 string Describe { get; } 14 } 15 /// <summary>獲得插件的窗體</summary> 16 public interface IForm 17 { 18 /// <summary>窗體名</summary> 19 string Text { get; } 20 21 /// <summary>窗體對象</summary> 22 Form GetForm { get; } 23 } MathAssistLibraryICommand接口
IForm接口
在插件項目中只要實現ICommand和IForm兩個接口即可,以SuperCalculator為例:
public partial class frmSuperCalculator : Form, IForm { string IForm.Text { get { return "計算器"; } } frmSuperCalculator frm; Form IForm.GetForm { get { if (frm == null || frm.IsDisposed) { frm = new frmSuperCalculator(); } return frm; } } ... }
public class Calculator : MathAssistLibrary.ICommand { string MathAssistLibrary.ICommand.Describe { get { return "cal命令可以進行相關的數學運算。比如cal 1+max(2,3)*2"; } } string MathAssistLibrary.ICommand.Name { get { return "cal"; } } string MathAssistLibrary.ICommand.Excute(string cmd) { try { Expression exp = new Expression(); exp.Format = cmd; return exp.Calculator().ToString(); } catch (ExpressionException e) { return string.Format("表達式出錯。出錯類型:{0},出錯位置{1}", e.Message, e.Index); } } }
FindDllFile()函數找到與程序同路徑下的所有dll文件,代碼如下:
1 List<string> FindDllFile(string foldername) { 2 DirectoryInfo dir = new DirectoryInfo(foldername); 3 FileInfo[] files = dir.GetFiles(); 4 List<string> result = new List<string>(); 5 6 foreach (FileInfo fi in files) { 7 if (fi.Name.ToUpper().EndsWith(".DLL")) 8 result.Add(fi.FullName); 9 } 10 return result; 11 } FindDllFileLoadOne()從一個文件中找一個特定的類型,並返回其對象,代碼如下:
private List<object> LoadOne(string filename, Type type) { List<object> result = new List<object>(); try { Assembly ass = Assembly.LoadFrom(filename); Module[] mods = ass.GetModules(); foreach (Module mod in mods) { Type[] typs = mod.GetTypes(); foreach (Type typ in typs) { if (type.IsAssignableFrom(typ)) { result.Add(ass.CreateInstance(typ.FullName)); } } } } catch (BadImageFormatException) { } return result; } // end func
先用Assembly.LoadFrom()加載程序集,然後獲取所有模塊,最後在所有模塊中用type.IsAssignableFrom()找與傳入參數type相匹配的類型,如果匹配那麼就創建一個對象並返回。
在主程序中分別用如下兩行代碼調用LoadOne()
List<object> cmd = LoadOne(filename, typeof(ICommand)); List<object> frm = LoadOne(filename, typeof(IForm));
這樣用cmd.Excute()就可以執行插件中實現的代碼,用frm.Show()就可以顯示插件中所實現的窗體。
現提供MathAssist.exe的下載路徑。在後面的文章中會給出整個程序的源碼,敬請期待~~
參數文獻: http://www.cnblogs.com/conexpress/archive/2009/03/04/MyCalculator_01.html