随笔 - 44  文章 - 0 评论 - 302 trackbacks - 80
<2007年2月>
28293031123
45678910
11121314151617
18192021222324
25262728123
45678910

本博客上的所有文章如非特别说明均为原创,如果要转载请注明文章出处。

与我联系

搜索

 

常用链接

留言簿(19)

我参加的小组

我参与的团队

随笔分类(40)

随笔档案(44)

文章分类

联系我

友情链接

积分与排名

  • 积分 - 169426
  • 排名 - 205

最新评论

阅读排行榜

评论排行榜

       不管你采用什么方式实现插件式的应用程序框架,核心还是动态加载,换句话说,没有动态加载技术也就无所谓插件式的应用程序框架了。使用Com实现的话,你可以利用ComAPI通过ProgID来动态创建COM对象,如果使用普通DLL,你需要使用Windows API函数LoadLibrary来动态加载DLL,并用GetProcAddress函数来获取函数的地址。而使用.NET技术的话,你需要使用Assembly类的几个静态的LoadLoadLoadFileLoadFrom)方法来动态加载汇集。
       一个Assembly里可以包含多个类型,由此可知,一个Assembly里也可以包含多个插件,就像前一篇文章所讲,只要它从IPlugin接口派生出来的类型,我们就承认它是一个插件类型。那么Assembly被动态加载了以后,我们如何获取Assembly里包含的插件实例呢?这就要用到反射(Reflection)机制了。我们需要使用AssemblyGetTypes静态方法来得到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
    }

}

      接下来我们创建一个Windows Application工程让主窗体派生于IApplication接口并实现IApplication接口的方法和属性,下来我们声明1MenuStrip1StatusStrip,让他们分别停靠在窗口的顶部和底端,接下来我们声明4ToolStripPanel,分别人他们停靠在上下左右四个边,最后我们创建一个ToolStrip,在上边添加一个按钮,当点击这个按钮的时候,我们动态的加载插件。
      为了方便演示,我们把生成的Assembly放置到固定的位置,以方便主程序加载,在本例里,我们在应用程序所在的文件夹里创建一个子文件夹PluginsE:\Practise\PluginSample\PluginSample\bin\Debug\Plugins),将插件工程产生的AssemblyFirstPlugin.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();
                }

            }


        }

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

posted on 2007-02-25 23:52 纶巾客 阅读(8799) 评论(14)  编辑 收藏 所属分类: .Net Framework

FeedBack:
#1楼  2007-02-26 09:26 天才書生      
一直在关注您的“插件”文章,觉得写得通俗易懂

但本人愚钝,小插件是能写出来,但我要写一个商业方面的程序,比如销售程序,想用插件来形式加载所有的模块,以便能实现用户的个性化需要也能以插件形式销售软件的功能

不知道大哥能不能讲解一下比较复杂的插件构架,比如像VS.NET的插件,为什么有的插件可以直接操作代码视图,难道MS留下了很详细的接口了??
  回复  引用  查看    
#2楼 [楼主] 2007-02-26 09:31 纶巾客      
@天才書生
我现在才刚刚开始,后边我会介绍一些这方面的内容。时间太少,不过我会尽快写的。
  回复  引用  查看    
#3楼  2007-02-26 09:59 妖居      
@天才書生
确实是这样的,VS给Addin的开发者留下了很丰富的接口,几乎所有的VS IDE对象都有相应的接口可以使用。
  回复  引用  查看    
#4楼  2007-02-26 10:35 Leepy      
我想问的是,在.net pet shop中用到的多层架构,也有用到类似Assembly加载某层dll文件,是否也算是插件式应用程序框架?谢谢
  回复  引用  查看    
#5楼  2007-02-26 10:58 JesseZhao      
好文章
  回复  引用  查看    
#6楼  2007-02-26 12:06 ego [未注册用户]
唉,用反射动态加载、卸载DLL很容易,难的是远程传递的Form不能作为MDI Form的父窗体,晕死了
  回复  引用    
#7楼 [楼主] 2007-02-26 12:16 纶巾客      
@Leepy
抱歉,pet shop我没有接触过。
  回复  引用  查看    
#8楼  2007-02-26 13:07 极地银狐.NET      
好文,要做成一个系列!
  回复  引用  查看    
#9楼  2007-02-26 13:40 吕震宇      
SharpDevelop的插件结构设计非常值得学习,我最近也打算写一篇关于对象创建的文章,其中就包含了一个基于SharpDevelop技术(经过很多简化)的插件程序。
  回复  引用  查看    
好文,寒假放假天天来看博客,今天终于看到又继续出连载了,期待下文
  回复  引用    
#11楼  2007-02-27 10:53 Artech      
建议添加.NET Framework 2.0 新的Configuration的内容, 使内容更充实。毕竟构建插件式的程序和Configuration密不可分。

  回复  引用  查看    
#12楼  2007-03-27 12:31 Roach [未注册用户]
abstruct Factory
  回复  引用    
#13楼  2007-04-10 10:14 haijer [未注册用户]
@ego
用API函数SetParent就可以了
  回复  引用    
#14楼  2008-04-02 20:00 wuhang      
好文章!最近作的项目正好用到~!
  回复  引用  查看    

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-02-26 08:39 编辑过


相关链接: