工作需要開發的一套插件框架,給應用程序提供靈活的插件支持,基於Dll / Interface實現。
先上個圖
這是個標准的基於插件的應用,下拉框里的就是由5個插件Dll提供的功能。主程序中定義了一個接口,而插件Dll則提供這個接口的實現。
使用也很簡單,在窗口上放置一個TExtensionManager組件,設置一下插件的讀取路徑就可以了。
框架中有3個重要概念,ServiceHost,Module(模塊)和擴展(Extension)
1.ServiceHost是整個框架的靈魂,不管是主程序中還是插件中,都通過他來查詢和使用其他的插件對象。
下面是一段使用示例代碼:(ServiceHost as ILoggingService).Log("This is a log");
(ServiceHost as IParameterService).SetValue("Param1", "Value1");
(ServiceHost as IMyPlugin).Foo();
(ServiceHost as IMyExtension).Execute();
2.Module是Extension的容器,即一個Module包含多個Extension。但實際上Module本身並不提供任何功能,也不提供Extension的管理功能,僅僅為Extension提供邏輯上的分組,同時為應用程序提供分組相關的信息。一個插件Dll中可以包含多個Module。
3.Extension是擴展對象管理類,當某個類實現了插件接口后,通過此對象對外發布,並由此對象管理其生命周期。
另外,框架里還提供了一些常用的服務,也是做為插件存在的,如上面的ILoggingService和IParameterService
IParameterService
參數服務,為應用程序和擴展提供參數支持,如 $(AppPath)
IRegistryService
注冊表服務,用於信息儲存和讀取
ILoggingService
日志服務,通過信道將消息輸出到不同的位置
IChannel
日志信道,用於將消息輸出到指定的位置
ILocalizationService
本地化服務,用於提供本地化的資源
ILocaleSource
本地化服務數據源
ISplashService
閃屏服務,用於訪問閃屏窗口
IDialogService
對話框服務,用於提供各種對話框
ILoginService
登錄服務,用於控制用戶登錄
再貼幾張Demo的圖吧
示例代碼:

unit uModule;
interface
implementation
uses
EFToolServices, EFModule, EFWinRegistry, EFLogging, EFParameter;
initialization
TInterfaceExtension.Create(IRegistryService, TWindowsRegistryService.Create,
' 2011.08.11 ', ' RegistryService ', ' IRegistryService Provider ', ' Author: sephil ');
TInterfaceExtension.Create(ILoggingService, TLoggingService.Create,
' 2011.08.11 ', ' LoggingService ', ' ILoggingService Provider ', ' Author: sephil ');
TInterfaceExtension.Create(IParameterService, TParameterService.Create,
' 2011.08.11 ', ' ParameterService ', ' IParameterService Provider ', ' Author: sephil ');
end.

unit uDllImpl;
interface
implementation
{ $I EFDef.inc }
uses
EFExports, { export dll entry proc }
EFSystem, EFToolServices, EFModule, EFSysUtils,
uDocIntf, Windows, Messages, SysUtils;
type
TDllObject = class(TInterfacedObject, IDllObject)
private
procedure ExecOpen;
procedure ExecInsert(CanUndo: Boolean);
end;
TDllModule = class(TModule)
protected
class function InitializeComponents(Host: IInterface): Integer; override;
procedure UpdateDesctiption; override;
public
procedure Initialize; override;
procedure Finalize; override;
end;
{ TDllObject }
procedure TDllObject.ExecOpen;
var
S: WideString;
begin
(ServiceHost as IParameterService).GetValue( ' $(APPPATH) ', S);
S := S + ' \TextDoc.txt ';
(ServiceHost as IDocument).Open(S);
end;
procedure TDllObject.ExecInsert(CanUndo: Boolean);
var
S: string;
begin
S := FormatDateTime( ' c ', Now);
SendMessage((ServiceHost as IDocument).GetHWND,
EM_REPLACESEL, WPARAM(CanUndo), LPARAM(PChar(S)));
end;
{ TDllModule }
function GetModule: string;
begin
SetString(Result, nil, MAX_PATH);
SetLength(Result, GetModuleFileName(HInstance, @Result[ 1], MAX_PATH));
end;
class function TDllModule.InitializeComponents(Host: IInterface): Integer;
var
S: WideString;
begin
(ServiceHost as ILoggingService).Write( ' TDllModule.InitializeComponents ');
(ServiceHost as IParameterService).GetValue( ' $(D2007) ', S);
if { $IFDEF DELPHI12_UP } not { $ENDIF } StrToBool(S) then Result := 0 else Result := 1;
if Result <> 0 then
(ServiceHost as ILoggingService).Write(ExtractFileName(GetModule) + ' skipped ')
else
(ServiceHost as ILoggingService).Write(ExtractFileName(GetModule) + ' loaded ');
end;
procedure TDllModule.UpdateDesctiption;
begin
// original info from version info
inherited;
end;
procedure TDllModule.Initialize;
var
Intf: ILoggingService;
begin
inherited;
(ServiceHost as ILoggingService).Write( ' TDllModule.Initialize ');
end;
procedure TDllModule.Finalize;
begin
inherited;
(ServiceHost as ILoggingService).Write( ' TDllModule.Finalize ');
end;
initialization
RegisterModuleClass(TDllModule);
TExtensionFactory.Create(IDllObject, TDllObject, ' 2011.08.08 ',
' Dll Object ', ' IDllObject implementation ', ' Author: sephil ');
end.