📄 un_pluginmanager.~pas
字号:
unit Un_PluginManager;
interface
uses
Classes, SysUtils, Forms, Un_Plugin, Un_PluginConfig;
type
//Id=bpl文件名+插件名
TPluginList=class
private
FStringList: TStringList;
function GetCount: Integer;
public
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure Delete(Index: Integer);
procedure AddPlugin(Id: string; APlugin: IPlugin);
function GetPlugin(Index: Integer): IPlugin;
function GetPluginById(const Id: string): IPlugin;
function IndexOfName(const Id: string): Integer;
property Count: Integer read GetCount;
end;
TPluginManager=class
private
FBplHModules: TStringList;
FPluginList: TPluginList;
function GetPlugin(const Id: string): IPlugin;
function GetCount: integer;
function GetPluginByIndex(const index: integer): IPlugin;
private
procedure Check(Bool: Boolean; ShowInfo: String);
function ChangeFileExtIsBPL(FileName: string): string;
protected
procedure UnloadPlugin(const Id: string); overload; //卸载指定的插件
procedure UnloadPlugin(const Index: Integer); overload; //卸载指定的插件
procedure LoadPlugin(const IniFileName, BplFileName: string);
procedure UnloadPlugins;
public
constructor Create;
destructor Destroy; override;
procedure LoadPlugins(Directory: string);
property Plugin[const id: string]: IPlugin read GetPlugin;
property PluginByIndex[const index: Integer]: IPlugin read GetPluginByIndex;
property Count: integer read GetCount;
property Plugins: TPluginList read FPluginList;
end;
TPluginFactory=class
private
FPluginManager: TPluginManager;
function GetPlugins: TPluginList;
public
constructor Create;
destructor Destroy; override;
class function Instance: TPluginFactory;
procedure LoadPlugins;
function GetPlugin(Id: string): IPlugin;
property Plugins: TPluginList read GetPlugins;
end;
implementation
{ TPluginList }
procedure TPluginList.AddPlugin(Id: string; APlugin: IPlugin);
begin
FStringList.AddObject(Id, Pointer(APlugin));
end;
procedure TPluginList.Clear;
begin
while FStringList.Count>0 do
Delete(0);
end;
constructor TPluginList.Create;
begin
FStringList:= TStringList.Create;
end;
procedure TPluginList.Delete(Index: Integer);
var
Plugin: IPlugin;
begin
Plugin:= GetPlugin(Index);
FStringList.Delete(Index);
Plugin:= nil;
end;
destructor TPluginList.Destroy;
begin
Clear;
FStringList.Free;
inherited;
end;
function TPluginList.GetCount: Integer;
begin
Result:= FStringList.Count;
end;
function TPluginList.GetPlugin(Index: Integer): IPlugin;
begin
Result:= IPlugin(Pointer(FStringList.Objects[Index]))
end;
function TPluginList.GetPluginById(const Id: string): IPlugin;
var
Index: Integer;
begin
Index:= IndexOfName(Id);
if Index=-1 then
raise Exception.Create('未找到插件:'+Id);
Result:= GetPlugin(Index);
end;
function TPluginList.IndexOfName(const Id: string): Integer;
begin
Result:= FStringList.IndexOf(Id);
end;
{ TPluginManager }
function TPluginManager.ChangeFileExtIsBPL(FileName: string): string;
begin
Result:= StringReplace(FileName,'.ini', '.bpl', [rfIgnoreCase]);
end;
procedure TPluginManager.Check(Bool: Boolean; ShowInfo: String);
begin
if (not Bool) then
raise Exception.Create(ShowInfo);
end;
constructor TPluginManager.Create;
begin
FPluginList:= TPluginList.Create;
FBplHModules:= TStringList.Create;
end;
destructor TPluginManager.Destroy;
begin
UnloadPlugins;
FPluginList.Free;
FBplHModules.Free;
inherited;
end;
function TPluginManager.GetCount: integer;
begin
Result:= FPluginList.Count;
end;
function TPluginManager.GetPlugin(const id: string): IPlugin;
var
Index: Integer;
begin
Index:= FPluginList.IndexOfName(id);
Check(index>=0, Format('未找到%s插件.', [id]));
Result:= GetPluginByIndex(index);
end;
function TPluginManager.GetPluginByIndex( const index: integer ): IPlugin;
begin
Check(Index<FPluginList.Count, IntToStr(index)+'超出范围 ,没有该索引.');
Result:= IPlugin(Pointer(FPluginList.GetPlugin(index)));
end;
procedure TPluginManager.LoadPlugin(const IniFileName, BplFileName: string );
var
i: Integer;
ImplClass : TPersistentClass;
obj : TPersistent;
Intf : IPlugin;
BplHandle : Cardinal;
PluginConfig: IPluginConfig;
begin
//载入bpl
BplHandle:= LoadPackage(BplFileName);
FBplHModules.Add(intToStr(BplHandle));
PluginConfig:= TIniPluginConfig.Create(IniFileName);
try
for i:= 0 to PluginConfig.GetConfig.Count-1 do begin
//存入接口变量
ImplClass:= GetClass(PluginConfig.GetConfig.Strings[i]);
Check(ImplClass<>nil,
Format('没有在%s中找到%s类.',
[BplFileName, PluginConfig.GetConfig.Strings[i]]));
obj:= ImplClass.Create;
Check(Supports(obj,
StringToGUID('{9C03B818-731D-4D8A-AD95-B8D87D07295E}'), Intf),
ImplClass.ClassName + '不支持插件接口IPlugin.');
FPluginList.AddPlugin(UpperCase(ExtractFileName(BplFileName)
+':'+PluginConfig.GetConfig.Strings[i]), Intf);
end;
finally
PluginConfig:= nil;
end;
end;
procedure TPluginManager.LoadPlugins(Directory: string);
var
i: Integer;
BplFileName: string;
PluginConfigFile: IPluginConfigFile;
begin
PluginConfigFile:= TIniPluginConfigFile.Create(Directory);
try
for i:= 0 to PluginConfigFile.GetConfigFiles.Count-1 do begin
BplFileName:= ChangeFileExtIsBPL(PluginConfigFile.GetConfigFiles.Strings[i]);
if FileExists(BplFileName) then
LoadPlugin(PluginConfigFile.GetConfigFiles.Strings[i], BplFileName);
end;
finally
PluginConfigFile:= nil;
end;
end;
procedure TPluginManager.UnloadPlugin(const id: string);
var
index: Integer;
begin
index:= FPluginList.IndexOfName(id);
Check(index>=0, Format('未找到%s插件.', [id]));
UnloadPlugin(index);
end;
procedure TPluginManager.UnloadPlugin(const index: Integer);
begin
FPluginList.Delete(index);
end;
procedure TPluginManager.UnloadPlugins;
var
i: Integer;
begin
for i:= FPluginList.Count - 1 downto 0 do UnloadPlugin(i);
for i:= 0 to FBplHModules.Count-1 do begin
UnloadPackage(StrToInt(FBplHModules.Strings[i]));
end;
end;
{ TPluginFactory }
constructor TPluginFactory.Create;
begin
FPluginManager:= TPluginManager.Create;
end;
destructor TPluginFactory.Destroy;
begin
FPluginManager.Free;
inherited;
end;
function TPluginFactory.GetPlugin(Id: string): IPlugin;
begin
Result:= FPluginManager.Plugin[Id];
end;
var
PluginFactory: TPluginFactory;
function TPluginFactory.GetPlugins: TPluginList;
begin
Result:= FPluginManager.Plugins;
end;
class function TPluginFactory.Instance: TPluginFactory;
begin
if PluginFactory=nil then
PluginFactory:= TPluginFactory.Create;
Result:= PluginFactory;
end;
procedure TPluginFactory.LoadPlugins;
var
PluginDir: string;
begin
PluginDir:= ExtractFilePath(Application.ExeName)+'plugins\';
FPluginManager.LoadPlugins(PluginDir);
end;
initialization
PluginFactory:= nil;
finalization
if PluginFactory<>nil then
FreeAndNil(PluginFactory);
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -