這是本人畢業(yè)設(shè)計(jì)的項(xiàng)目,一直想將其整理成文,可一不小心4年就過去了(這個(gè)時(shí)間又可以讀個(gè)大學(xué)了)。現(xiàn)在給自己定一個(gè)目標(biāo),一個(gè)月時(shí)間里將項(xiàng)目的所有關(guān)鍵點(diǎn)都整理出來。不然真怕一眨眼又一個(gè)4年過去了,而代碼依然躺在硬盤里。
項(xiàng)目取名MathAssist,使用vs2008。分成四個(gè)子項(xiàng)目:
其主程序可以從插件中掃描可用的命令,也可以顯示插件中可用的窗體。如下是主程序界面,其加載了兩個(gè)插件:“superCalculator”和“命令證明”。它們分別提供命令cal PRove。

點(diǎn)擊菜單項(xiàng)"插件"的子菜單后可以分別打開兩個(gè)插件中實(shí)現(xiàn)的窗口。如下圖


分別實(shí)現(xiàn)了大數(shù)計(jì)算和邏輯命題的證明。
在這篇前言中就先只介紹插件機(jī)制的實(shí)現(xiàn)吧,大數(shù)計(jì)算和邏輯命題的證明就留給后面的系列。
在MathAssistLibrary項(xiàng)目中只定義了兩個(gè)接口: ICommand, IForm,分別用于提供命令行功能和窗口功能。

1 /// <summary>命令接口</summary> 2 public interface ICommand 3 { 4 /// <summary>命令名稱</summary> 5 string Name { get; } 6 7 /// <summary>執(zhí)行命令</summary> 8 /// <param name="cmd">命令參數(shù)</param> 9 /// <returns>返回的結(jié)果</returns>10 string Excute( string cmd );11 12 /// <summary>對(duì)命令的使用作相應(yīng)的說明</summary>13 string Describe { get; }14 }15 /// <summary>獲得插件的窗體</summary>16 public interface IForm17 {18 /// <summary>窗體名</summary>19 string Text { get; }20 21 /// <summary>窗體對(duì)象</summary>22 Form GetForm { get; }23 }MathAssistLibraryICommand接口
IForm接口
在插件項(xiàng)目中只要實(shí)現(xiàn)ICommand和IForm兩個(gè)接口即可,以SuperCalculator為例:
public partial class frmSuperCalculator : Form, IForm{ string IForm.Text { get { return "計(jì)算器"; } } 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命令可以進(jìn)行相關(guān)的數(shù)學(xué)運(yùn)算。比如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("表達(dá)式出錯(cuò)。出錯(cuò)類型:{0},出錯(cuò)位置{1}", e.Message, e.Index); } }}FindDllFile()函數(shù)找到與程序同路徑下的所有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()從一個(gè)文件中找一個(gè)特定的類型,并返回其對(duì)象,代碼如下:
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()找與傳入?yún)?shù)type相匹配的類型,如果匹配那么就創(chuàng)建一個(gè)對(duì)象并返回。
在主程序中分別用如下兩行代碼調(diào)用LoadOne()
List<object> cmd = LoadOne(filename, typeof(ICommand));List<object> frm = LoadOne(filename, typeof(IForm));
這樣用cmd.Excute()就可以執(zhí)行插件中實(shí)現(xiàn)的代碼,用frm.Show()就可以顯示插件中所實(shí)現(xiàn)的窗體。
現(xiàn)提供MathAssist.exe的下載路徑。在后面的文章中會(huì)給出整個(gè)程序的源碼,敬請(qǐng)期待~~
參數(shù)文獻(xiàn): http://www.survivalescaperooms.com/conexpress/archive/2009/03/04/MyCalculator_01.html
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注