半路出家的delphier一如我,对于win32api式的调用有着近乎厌恶的抵触情绪,我很早以前看c++的教程时看到lptrXXXXX的变量就头大,以至于到现在都不会用c++,都不曾写成功过那怕一个hello world程序,所以对于dll式的导出函数后面加stdcall使用右到左的参数调用方式,总觉得没有delphi的美感.再加上看到了许多bpl可以导出类,而dll很麻烦的文章,更是坚定了我的方向.
开始吧..
一个插件系统需要什么?
一个最小的插件系统当然需要插件本身,调用插件的容器,最后需要契约.
契约是什么呢?契约就是两个对象相互沟通的一个标准,这个标准应该统一,这样容器才能和不同的插件通讯.我们可以使用接口来表述这个契约.例如
type
IPlugin = interface
[''{48BF4000-B028-4B57-9955-B1A8305DA394}'']
procedure Execute;
end;
容器,它可以配置加载哪些插件,并能调用插件的功能,并和插件交互数据,这种数据应该有统一性,因此我们的目标当然是需要和插件能够交互TObject,因为我们可以封装任何的数据在TObject中去,至于这个TObject中是些什么什么数据,只需要插件和容器知道就可以了.那么我们修改契约如下:
type
IPlugin = interface
[''{48BF4000-B028-4B57-9955-B1A8305DA394}'']
function GetObject: TObject;
procedure SetObject( value: TObject );
procedure Execute;
end;
插件,我们使用实现了接口的一个bpl来构建插件,让容器动态载入一个bpl,然后访问其中的IPlugin来调用插件
coding吧
我们构造一个容器,它动态的载入一个bpl,并且通过预定义的名称来访问其中的IPlugin,并调用IPlugin.Execute,这个预定义的名称其实是在bpl中实现了IPlugin的类的名称,这个类的名称我们可以通过修改bpl的名称或者同时发布一个配置文件来让容器获得.现在我们先暂时写死在程序里,毕竟这个问题是个小问题
构建插件
new->package生成一个package,就用''package1''的缺省名称,new->unit
unit TPluginImpl1;
interface
uses uIPlugin, dialogs, Classes;
type
{$M+}
TPlugin = class( TInterfacedPersistent, IPlugin )
function GetObject: TObject;
procedure SetObject( value: TObject );
procedure Execute;
private
FMsg: string;
public
procedure AfterConstruction; override;
end;
{$M-}
implementation
{ TPlugin }
procedure TPlugin.AfterConstruction;
begin
inherited;
FMsg := ''init String'';
end;
procedure TPlugin.Execute;
begin
showmessage( FMsg );
end;
function TPlugin.GetObject: TObject;
begin
result := TObject( FMsg );
end;
procedure TPlugin.SetObject( value: TObject );
begin
FMs