不管你采用什么方式实现插件式的应用程序框架,核心还是动态加载,换句话说,没有动态加载技术也就无所谓插件式的应用程序框架了。使用Com实现的话,你可以利用Com的API通过ProgID来动态创建COM对象,如果使用普通DLL,你需要使用Windows 的API函数LoadLibrary来动态加载DLL,并用GetProcAddress函数来获取函数的地址。而使用​​.NET​​技术的话,你需要使用Assembly类的几个静态的Load(Load,LoadFile,LoadFrom)方法来动态加载汇集。

       一个Assembly里可以包含多个类型,由此可知,一个Assembly里也可以包含多个插件,就像前一篇文章所讲,只要它从IPlugin接口派生出来的类型,我们就承认它是一个插件类型。那么Assembly被动态加载了以后,我们如何获取Assembly里包含的插件实例呢?这就要用到反射(Reflection)机制了。我们需要使用Assembly的GetTypes静态方法来得到Assembly里所包含的所有的类型,然后遍历所有的类型并判断每一个类型是不是从IPlugin接口派生出来的,如果是,我们就使用Activator的静态方法CreateInstance方法来获得这个插件的实例。​​.NET​​的动态加载就是这几个步骤。下来,我做一个简单的例子来演练一下动态加载。首先声明一点,这个例子非常简单,纯粹是为了演练动态加载,我们的真正的插件式的应用程序框架里会有专门的PluginService来负责插件的加载,卸载。 

      我们的插件位于一个DLL里,所以我们首先创建一个Class library工程。创建一个FirstPlugin类让它派生于IPlugin接口,并实现接口的方法和属性,由于本文的目的是演示动态加载,所以IPlugin接口的Loading事件我们就不提供默认的实现了,虽然编译的时候会给出一个警告,我们不必理会它。这个插件的功能就是在应用程序里创建一个停靠在主窗体底部的ToolStrip,这个ToolStrip上有一个按钮,点击这个按钮,会弹出一个MessageBox显示“The first plugin”。下面是代码:

   

构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载using System;

构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载using System.Collections.Generic;

构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载using System.Text;

构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载using PluginFramework;

构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载using System.Windows.Forms;

构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载

构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载namespace FirstPlugin

构建插件式的应用程序框架(三)----动态加载(ZT)_加载_08构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载_09构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11    public class FirstPlugin:IPlugin

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13    构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11        private IApplication application = null;

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11        private String name="";

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11        private String description = "";

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12        IPlugin Members#region IPlugin Members

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11        public IApplication Application

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13        构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            get

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13            构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                return application;

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31            }

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            set

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13            构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                application = value;

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31            }

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31        }

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11        public string Name

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13        构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            get

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13            构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                return name;

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31            }

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            set

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13            构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                name = value;

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31            }

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31        }

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11        public string Description

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13        构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            get

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13            构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                return description;

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31            }

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            set

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13            构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                description = value;

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31            }

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31        }

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11        public void Load()

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13        构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            if (application != null && application.BottomToolPanel != null)

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13            构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                //创建一个向主程序添加的ToolStrip

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                ToolStrip sampleToolStrip = new ToolStrip();

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                ToolStripButton button = new ToolStripButton("Click Me");

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                button.Click += new EventHandler(button_Click);

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                sampleToolStrip.Items.Add(button);

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                //在主程序的底端添加ToolStrip

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                application.BottomToolPanel.Controls.Add(sampleToolStrip);

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31            }

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31        }

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11        void button_Click(object sender, EventArgs e)

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13        构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            MessageBox.Show("The first plugin");

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31        }

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11        //相关的文章主要讲动态加载,所以卸载就不实现了

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11        public void UnLoad()

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13        构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            throw new Exception("The method or operation is not implemented.");

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31        }

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11        public event EventHandler<EventArgs> Loading;

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31        #endregion

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31    }

构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载_114}

构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载


      接下来我们创建一个Windows Application工程让主窗体派生于IApplication接口并实现IApplication接口的方法和属性,下来我们声明1个MenuStrip和1个StatusStrip,让他们分别停靠在窗口的顶部和底端,接下来我们声明4个ToolStripPanel,分别人他们停靠在上下左右四个边,最后我们创建一个ToolStrip,在上边添加一个按钮,当点击这个按钮的时候,我们动态的加载插件。

      为了方便演示,我们把生成的Assembly放置到固定的位置,以方便主程序加载,在本例里,我们在应用程序所在的文件夹里创建一个子文件夹Plugins(E:\Practise\PluginSample\PluginSample\bin\Debug\Plugins),将插件工程产生的Assembly(FirstPlugin.dll)放置在这个子文件夹。下面是动态加载的代码:      


构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载private void toolStripButton1_Click(object sender, EventArgs e)

构建插件式的应用程序框架(三)----动态加载(ZT)_加载_08构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载_09        构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            //动态加载插件,为了方便起见,我直接给出插件所在的位置

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            String pluginFilePath = Path.GetDirectoryName(Application.ExecutablePath) + "\\plugins\\FirstPlugin.dll";

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            Assembly assembly = Assembly.LoadFile(pluginFilePath);

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            //得到Assembly中的所有类型

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            Type[] types = assembly.GetTypes();

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            //遍历所有的类型,找到插件类型,并创建插件实例并加载

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11            foreach (Type type in types)

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13            构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                if (type.GetInterface("IPlugin") != null)//判断类型是否派生自IPlugin接口

构建插件式的应用程序框架(三)----动态加载(ZT)_.net_12构建插件式的应用程序框架(三)----动态加载(ZT)_.net_13                构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_10{

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                    IPlugin plugin = (IPlugin)Activator.CreateInstance(type);//创建插件实例

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                    plugin.Application = this;

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11                    plugin.Load();

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31                }

构建插件式的应用程序框架(三)----动态加载(ZT)_静态方法_31            }

构建插件式的应用程序框架(三)----动态加载(ZT)_应用程序_11

构建插件式的应用程序框架(三)----动态加载(ZT)_动态加载_114        }