转] 从 dll 程序集中动态加载窗体

简介:

无涯 原文 从 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 文件包含多个窗体时:

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

 

没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。



    本文转自wenglabs博客园博客,原文链接:http://www.cnblogs.com/arxive/p/5823560.html ,如需转载请自行联系原作者
相关文章
|
7月前
|
C++
MFC创建带窗口的DLL
MFC创建带窗口的DLL
142 0
第一次机房收费系统——注册DLL和OCX控件
第一次机房收费系统——注册DLL和OCX控件
|
C# 图形学 C++
Unity与 DLL文件 ☀️| 怎样使用 C# 类库 生成一个DLL文件 并 调用!
📢前言 🎬生成DLL文件 🎥使用 C#类库 将Unity中的脚本打包成 DLL文件 并调用 🏳️‍🌈第一步:打开Visual Studio之后,新建一个项目 🏳️‍🌈第二步:选择类库(.NET Framework),改个名字,选择一个位置路径 🏳️‍🌈第三步:然后在创建的脚本中简单写一点代码,如下所示 🏳️‍🌈第四步:然后在解决方案资源管理器右键这个脚本 -> 添加 -> 引用 🏳️‍🌈第五步:然后点击浏览,找到Unity安装路径 -> Editor -> Data -> Managed 下的这两个DLL 文件,点击添加!
Unity与 DLL文件 ☀️| 怎样使用 C# 类库 生成一个DLL文件 并 调用!
|
程序员 编译器 Linux
Unity与 DLL文件 ☀️| 什么是DLL✨?
📣前言 在之前的文章有介绍过so文件,那本篇文章就来介绍一些DLL文件吧! 提起DLL文件,大家肯定不会陌生,就算自己没编写生成过DLL文件,那也一定见过! Windows系统打开电脑C盘的System文件夹,往下一拉就会发现有超级多的带有.dll后缀的文件! 那DLL文件到底是个怎样的存在呢?本篇文章就来好好研究一下这个DLL文件究竟是个啥!
Unity与 DLL文件 ☀️| 什么是DLL✨?
MFC创建动态链接库DLL并调用方法详解
实例一: 1、创建一个动态链接库工程,如login_dll。 2、在原工程头文件或者新建头文件如showdlg.h定义动态链接库的导出函数,代码如下: #include "stdafx.h"#define EXPORT __declspec(dllexport)extern "C"  EXPO...
3646 0
|
C#
XamlReader 动态加载XAML
原文:XamlReader 动态加载XAML XAML: CS: using (FileStream s = new FileStream(@"C:\Users\Lin.
1141 0
|
C#
WPF加载程序集中字符串资源
原文:WPF加载程序集中字符串资源   WPF资源 WPF资源使用其实的也是resources格式嵌入资源,默认的资源名称为"应用程序名.g.resources",不过WPF资源使用的pack URI来访问资源。
1011 0
|
C#
c#实现动态加载Dll
原文:c#实现动态加载Dll 原理如下: 1、利用反射进行动态加载和调用. Assembly assembly=Assembly.
2713 0
|
Android开发 iOS开发 图形学