| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 7354 人关注过本帖, 3 人收藏
标题:[经验交流] 简易插件机制的实现方法浅谈
只看楼主 加入收藏
野比
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:24
帖 子:1627
专家分:516
注 册:2007-5-24
结帖率:100%
收藏(3)
 问题点数:0 回复次数:15 
[经验交流] 简易插件机制的实现方法浅谈
简易插件机制的实现方法浅谈
野比 著

下载例程源代码:
PluginDemo.rar (42.54 KB)


简介

插件(Plugin),是现代软件设计的一大亮点。通过插件机制,我们的应用程序可以最大化的获得可扩展性、适应性和稳定性,而且便于软件的维护和升级。对于插件的优缺点,我不做探讨。

在本文中你将了解到如何为应用程序实现一种简单、直接的插件机制。使用此种插件机制,我们可以开发出高度可扩展的应用程序,提高程序整体水平。

结构

我们的程序可以加载不同功能的插件——可以是我们自己或其他任何人开发的——而不需要事先知道插件所完成的功能。当然,类似如何加载插件这样的基本方法程序是约定好的。

这里使用到了程序设计的一种方法:后期绑定([it]Late-Binding[/it])。

简单来说,我们要做的就是让程序在运行时动态加载保存于插件中的方法、属性等,并对其进行调用,以实现相应功能。为了管理插件,需要为插件提供一个统一的管理接口。插件与程序通过接口进行交流。

设计插件机制如下图所示:
图片附件: 游客没有浏览图片的权限,请 登录注册


实现

通过分析设计,我们确定按照以下方式实现插件机制:

    [*]应用程序    exe    控制台程序
    [*]插件接口    dll    类库
    [*]插件        dll    类库


简单起见,我们的应用程序不适用 GUI 。关于 GUI 的使用,包括如何在插件中实现界面,请参考本文提供的源程序 Demo。

为了避免使用反射(Reflection)等高级概念,这里使用 System.Runtime.Remoting 命名空间中 Activator 类。

该类包含 Activator.CreateInstanceFrom() 方法,可以从任意路径的插件加载其中的功能类。只需要一句代码:
System.Activator.CreateInstanceFrom(string pluginFilePath, string pluginClassName);


该方法返回的是 ObjectHandle 类型的对象句柄,需要对其进行解包,才能直接使用。解包使用如下代码:
ObjectHandle objHandle = System.Activator.CreateInstanceFrom("..//..//plugins//pluginA.dll", "PluginA");
//解包
IPlugin plugin = objHandle.Unwrap() as IPlugin;


其中,假设我们的插件 PluginA.dll 存放于 ../plugins 目录中。解包后得到的 plugin 对象是插件功能类 PluginA的一个实例。之后对 plugin 对象的相关方法进行调用就可以使用插件了。例如,假设插件 pluginA.dll 的功能类 PluginA 包含 ShowGUI() 方法显示图形界面,则使用下面的代码对其进行调用:
plugin.ShowGUI();


这样我们就完成了一种简易的插件机制。最后 Demo 运行效果如下图:
图片附件: 游客没有浏览图片的权限,请 登录注册


扩展

插件也许会有和主程序交流的需求,所以我们可以为插件增加一个主程序接口 IPluginHost,其中包含了主程序的相关信息。然后在主程序(从此 IPluginHost 接口继承)加载插件时对其进行注册,这样即可在插件中对主程序进行访问。

在 插件接口.dll 中声明:
public interface IPluginHost
{
   
bool Register(IPlugin plugin);
}


在主程序中实现此接口:
public bool Register(IPlugin plugin)
{
   
//对 plugin 进行操作
    //对主程序进行操作
}


我们还需要在 IPlugin 接口中增加 Host 属性,并在插件中对其进行实现:
//IPlugin 中增加
IPluginHost Host{ get;set; }

//插件中增加
private IPluginHost pluginHost;
public IPluginHost Host
{
   
get { return pluginHost; }
   
set
   
{
        
pluginHost = value;
        
pluginHost.Register(this);
   
}
}


参考文献

1. Mike Pagel [德国], [it]Enabling Your Application to Become a Plugin Host[/it]
2. Shoki [印度], [it]Plugin Architecture using C#[/it]
3. Roy Osherove [以色列], [it]Add run-time functionality to your application by providing a plug-in mechanism[/it]

[[it] 本帖最后由 野比 于 2009-3-17 22:35 编辑 [/it]]
搜索更多相关主题的帖子: 机制 插件 经验 交流 
2008-04-11 02:01
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 
老兄的发一贴和我发的一贴表达了差不多一样的思想吧.我发上来可是没人问津..
我是用反射实现的.
引用视图:
图片附件: 游客没有浏览图片的权限,请 登录注册

程序代码:
//ICar.dll
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ICar
{
    public interface ICar
    {
        string GetCar();
    }
}

程序代码:
//FuTe.dll
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FuTe
{
    public class FuTe : ICar.ICar
    {
    
        public string GetCar()
        {
            return "FuTe";
        }
    }
}

程序代码:
//CarFactory.dll
using System;
using System.Reflection;

namespace CarFactory
{
    public class CarFactory
    {

        public static ICar.ICar CreateCar(string CarFileName)
        {
            var CarAssembly = Assembly.LoadFrom(CarFileName);
            ICar.ICar CarType = null;
            foreach (var tmpCarType in CarAssembly.GetTypes())
            {
                    CarType = (ICar.ICar)Activator.CreateInstance(tmpCarType);
                    break;
            }
            return CarType;
        }
    }
}

程序代码:
//测试程序ConsoleApplication6.exe
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            var myCar = CarFactory.CarFactory.CreateCar(@"FuTe.dll");
            var CarName = myCar.GetCar();
            Console.WriteLine(CarName);
            Console.ReadLine();
        }
    }
}

源码在:
https://bbs.bccn.net/thread-206893-1-1.html

[[it] 本帖最后由 ioriliao 于 2008-4-11 14:03 编辑 [/it]]

/images/2011/147787/2011051411021524.jpg" border="0" />
2008-04-11 13:41
野比
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:24
帖 子:1627
专家分:516
注 册:2007-5-24
收藏
得分:0 
恩,思想差不多。
我关注的是如何分离插件和主程序以实现 Host-Plugin 模式的程序。

女侠,约吗?
2008-04-11 14:13
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 
Host-Plugin模式的程序的难点是如何把插件与主程序偶合起来吧...

/images/2011/147787/2011051411021524.jpg" border="0" />
2008-04-11 14:21
野比
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:24
帖 子:1627
专家分:516
注 册:2007-5-24
收藏
得分:0 
[bo]以下是引用 [un]ioriliao[/un] 在 2008-4-11 14:21 的发言:[/bo]

Host-Plugin模式的程序的难点是如何把插件与主程序偶合起来吧...

No, 难点是如何尽量降低耦合程度,以便于泛化。
简单来说,主程序和插件相互认知越少越好。
我正在研究这方面,希望了解更多。

女侠,约吗?
2008-04-11 14:41
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 
呵呵...那可能是我误解了...老兄能否举几个实例...

/images/2011/147787/2011051411021524.jpg" border="0" />
2008-04-11 14:56
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 
我把我上面发的工程改了下,请老兄看看你所指的插入式是否是如此的
https://bbs.bccn.net/thread-208438-1-1.html
谢谢.

/images/2011/147787/2011051411021524.jpg" border="0" />
2008-04-11 17:26
野比
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:24
帖 子:1627
专家分:516
注 册:2007-5-24
收藏
得分:0 
看了,差不多。大概是这个意思。
P.S.
福特 Ford
奔驰 Benz
^o^

女侠,约吗?
2008-04-11 20:10
野比
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:24
帖 子:1627
专家分:516
注 册:2007-5-24
收藏
得分:0 
ioriliao 注意到没有,你所用的方法和我的一样,同样是调用 System.Activator.CreateInstance() 家族方法进行 Late-Binding。

女侠,约吗?
2008-04-11 20:12
ioriliao
Rank: 7Rank: 7Rank: 7
来 自:广东
等 级:贵宾
威 望:32
帖 子:2829
专家分:647
注 册:2006-11-30
收藏
得分:0 
[bo]以下是引用 [un]野比[/un] 在 2008-4-11 20:10 的发言:[/bo]

看了,差不多。大概是这个意思。
P.S.
福特 Ford
奔驰 Benz
^o^

^_^,读得像就是了...呵呵...

/images/2011/147787/2011051411021524.jpg" border="0" />
2008-04-12 10:23
快速回复:[经验交流] 简易插件机制的实现方法浅谈
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.024574 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved