原文
昨天晚上花了一晚上时间写了一个从程序集中动态加载窗体的程序.将任何包含窗体的代码编译成 dll 文件,再把 dll 文件拷贝到本程序的目录下,本程序运行时即可动态检查到 dll 文件中的窗体,将窗体类的类型在程序菜单中显示出来,点击菜单即可运行对应的窗体.
本程序主要用到了 Assembly 类动态加载程序集,再得到程序集中包含类的 Type 类型,动态生成类实例,动态调用类方法.个人觉得这是一种提供高度松耦合,可随意扩展的程序结构框架,希望和大家探讨一下这种框架的应用前景!关键性代码如下:
using System;using System.Drawing;using System.IO;using System.Reflection;using System.Collections;using System.ComponentModel;using System.Windows.Forms;using System.Data;namespace WindowsFormTest{ ////// Form1 的摘要说明。 /// public class FrmMain : System.Windows.Forms.Form { private int formNum; private ArrayList formTypes = new ArrayList(); private ArrayList formObjects = new ArrayList(); private System.Windows.Forms.MainMenu mnuMain; private System.Windows.Forms.MenuItem mnuItmRun; private System.Windows.Forms.MenuItem mnuItemWindow; private System.Windows.Forms.MenuItem mnuItmHelp; private System.Windows.Forms.MenuItem mnuItmCascade; private System.Windows.Forms.MenuItem mnuItmTileHorizontal; private System.Windows.Forms.MenuItem mnuItmTileVertical; private System.Windows.Forms.MenuItem menuItem1; private System.Windows.Forms.MenuItem mnuItmAbout; private System.Windows.Forms.StatusBar staBarMain; private System.Windows.Forms.StatusBarPanel pnlInfo; private System.Windows.Forms.StatusBarPanel pnlNum; ////// 必需的设计器变量。 /// private System.ComponentModel.Container components = null; public FrmMain() { // // Windows 窗体设计器支持所必需的 // InitializeComponent(); // // TODO: 在 InitializeComponent 调用后添加任何构造函数代码 // } ////// 清理所有正在使用的资源。 /// protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } Windows 窗体设计器生成的代码 private void FrmMain_Load(object sender, System.EventArgs e) { Assembly assembly = null; string windowsPath = Path.Combine(Application.StartupPath, "Windows"); foreach (string dllFile in Directory.GetFiles(windowsPath, "*.dll")) { assembly = Assembly.LoadFile(dllFile); Type[] types = assembly.GetTypes(); foreach (Type t in types) { if (t.BaseType == typeof(Form)) { this.formTypes.Add(t); MenuItem item = this.mnuItmRun.MenuItems.Add(t.FullName); item.Click += new EventHandler(menuItemNewItem_Click); } } } } private void menuItemNewItem_Click(object sender, EventArgs e) { MenuItem item = (MenuItem)sender; Type t = (Type)(this.formTypes[item.Index]); Object obj = Activator.CreateInstance(t); this.formObjects.Add(obj); formNum += 1; t.InvokeMember("MdiParent", BindingFlags.SetProperty, null, obj, new object[] { this}); t.InvokeMember("Text", BindingFlags.SetProperty, null, obj, new object[] {t.FullName+" 窗体:"+formNum}); t.InvokeMember ("Show", BindingFlags.InvokeMethod, null, obj, new object [] {}); ((Form)obj).Closing += new CancelEventHandler(FrmWindow_Closing); ((Form)obj).Activated += new EventHandler(FrmWindow_Activated); MenuItem menuItem = this.mnuItemWindow.MenuItems.Add(((Form)obj).Text); menuItem.Click += new EventHandler(menuItemWindow_Click); this.pnlNum.Text = "当前装载了"+this.formObjects.Count+"个窗体"; this.pnlInfo.Text = "当前活动窗体:"+this.ActiveMdiChild.Text; } private void menuItemWindow_Click(object sender, System.EventArgs e) { MenuItem item = (MenuItem)sender; ((Form)(this.formObjects[item.Index-4])).Activate(); this.pnlNum.Text = "当前装载了"+this.formObjects.Count+"个窗体"; this.pnlInfo.Text = "当前活动窗体:"+this.ActiveMdiChild.Text; } private void FrmWindow_Activated(object sender, System.EventArgs e) { this.pnlNum.Text = "当前装载了"+this.formObjects.Count+"个窗体"; this.pnlInfo.Text = "当前活动窗体:"+this.ActiveMdiChild.Text; } private void FrmWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) { for (int i=0; i
程序源码下载:
程序截图单个 dll 文件包含一个窗体时:当程序目录下的所有程序集中包含一个窗体类时,程序运行界面:
多个 dll 文件包含多个窗体时:
当程序目录下的所有程序集中包含多个窗体类时,程序运行界面: