从 dll 程序集中动态加载窗体 [原创]

荒凉一梦 提交于 2020-02-27 12:40:31

 昨天晚上花了一晚上时间写了一个从程序集中动态加载窗体的程序.将任何包含窗体的代码编译成 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 文件包含多个窗体时:

当程序目录下的所有程序集中包含多个窗体类时,程序运行界面:



  欢迎大家提出意见,共同探讨!

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!