[轉] 從 dll 程式集中動態載入窗體

weixin_33816946發表於2016-08-30

無涯 原文 從 dll 程式集中動態載入窗體 [原創]

  昨天晚上花了一晚上時間寫了一個從程式集中動態載入窗體的程式.將任何包含窗體的程式碼編譯成 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
{
    /// <summary>
    /// Form1 的摘要說明。
    /// </summary>
    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;
        /// <summary>
        /// 必需的設計器變數。
        /// </summary>
        private System.ComponentModel.Container components = null;

        public FrmMain()
        {
            //
            // Windows 窗體設計器支援所必需的
            //
            InitializeComponent();

            //
            // TODO: 在 InitializeComponent 呼叫後新增任何建構函式程式碼
            //
        }

        /// <summary>
        /// 清理所有正在使用的資源。
        /// </summary>
        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<this.formObjects.Count; i++)
            {
                if (((Form)this.formObjects[i]).Text == ((Form)sender).Text)
                {
                    this.formObjects.RemoveAt(i);
                    this.mnuItemWindow.MenuItems.RemoveAt(i+4);

                    this.pnlNum.Text = "當前裝載了"+this.formObjects.Count+"個窗體";
                    this.pnlInfo.Text = "當前活動窗體:"+this.ActiveMdiChild.Text;
                    break;
                }
            }
        }

        private void mnuItmCascade_Click(object sender, System.EventArgs e)
        {
            this.LayoutMdi(MdiLayout.Cascade);
        }

        private void mnuItmTileHorizontal_Click(object sender, System.EventArgs e)
        {
            this.LayoutMdi(MdiLayout.TileHorizontal);
        }

        private void mnuItmTileVertical_Click(object sender, System.EventArgs e)
        {
            this.LayoutMdi(MdiLayout.TileVertical);
        }

        private void mnuItmAbout_Click(object sender, System.EventArgs e)
        {
            new FrmAbout().ShowDialog(this);
        }
    }
}

程式原始碼下載:/Files/Infinity/WindowsForm.rar


程式截圖
單個 dll 檔案包含一個窗體時:

當程式目錄下的所有程式集中包含一個窗體類時,程式執行介面:

多個 dll 檔案包含多個窗體時:

當程式目錄下的所有程式集中包含多個窗體類時,程式執行介面:

 

相關文章