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

不管你采用什么方式实现插件式的应用程序框架,核心还是动态加载,换句话说,没有动态加载技术也就无所谓插件式的应用程序框架了。使用 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 ”。下面是代码:
   
using  System;
using  System.Collections.Generic;
using  System.Text;
using  PluginFramework;
using  System.Windows.Forms;

namespace  FirstPlugin
{
    
public class FirstPlugin:IPlugin
    
{
        
private IApplication application = null;
        
private String name="";
        
private String description = "";

        
IPlugin Members#region IPlugin Members

        
public IApplication Application
        
{
            
get
            
{
                
return application;
            }

            
set
            
{
                application 
= value;
            }

        }


        
public string Name
        
{
            
get
            
{
                
return name;
            }

            
set
            
{
                name 
= value;
            }

        }


        
public string Description
        
{
            
get
            
{
                
return description;
            }

            
set
            
{
                description 
= value;
            }

        }


        
public void Load()
        
{
            
if (application != null && application.BottomToolPanel != null)
            
{
                
//创建一个向主程序添加的ToolStrip
                ToolStrip sampleToolStrip = new ToolStrip();
                ToolStripButton button 
= new ToolStripButton("Click Me");
                button.Click 
+= new EventHandler(button_Click);
                sampleToolStrip.Items.Add(button);

                
//在主程序的底端添加ToolStrip
                application.BottomToolPanel.Controls.Add(sampleToolStrip);
            }

        }


        
void button_Click(object sender, EventArgs e)
        
{
            MessageBox.Show(
"The first plugin");
        }


        
//相关的文章主要讲动态加载,所以卸载就不实现了
        public void UnLoad()
        
{
            
throw new Exception("The method or operation is not implemented.");
        }


        
public event EventHandler<EventArgs> Loading;

        
#endregion

    }

}

      接下来我们创建一个 Windows Application 工程让主窗体派生于 IApplication 接口并实现 IApplication 接口的方法和属性,下来我们声明 1 MenuStrip 1 StatusStrip ,让他们分别停靠在窗口的顶部和底端,接下来我们声明 4 ToolStripPanel ,分别人他们停靠在上下左右四个边,最后我们创建一个 ToolStrip, 在上边添加一个按钮,当点击这个按钮的时候,我们动态的加载插件。
      为了方便演示,我们把生成的 Assembly 放置到固定的位置,以方便主程序加载,在本例里,我们在应用程序所在的文件夹里创建一个子文件夹 Plugins E:\Practise\PluginSample\PluginSample\bin\Debug\Plugins ),将插件工程产生的 Assembly FirstPlugin.dll )放置在这个子文件夹。下面是动态加载的代码:      
private   void  toolStripButton1_Click( object  sender, EventArgs e)
        
{
            
//动态加载插件,为了方便起见,我直接给出插件所在的位置
            String pluginFilePath = Path.GetDirectoryName(Application.ExecutablePath) + "\\plugins\\FirstPlugin.dll";
            Assembly assembly 
= Assembly.LoadFile(pluginFilePath);

            
//得到Assembly中的所有类型
            Type[] types = assembly.GetTypes();

            
//遍历所有的类型,找到插件类型,并创建插件实例并加载
            foreach (Type type in types)
            
{
                
if (type.GetInterface("IPlugin"!= null)//判断类型是否派生自IPlugin接口
                {
                    IPlugin plugin 
= (IPlugin)Activator.CreateInstance(type);//创建插件实例
                    plugin.Application = this;
                    plugin.Load();
                }

            }


        }
    我把完整源代码也附上,方便大家使用:源代码下载

你可能感兴趣的:(windows,职场,应用程序,休闲)