首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 利用 GetClass/RegisterClass 實現字符串動態實例化類:插件架構核心技術

     編輯:Delphi

前言

在需要根據配置文件、用戶選擇、腳本指令動態創建具體類實例的場景(如日誌輸出器切換、算法策略替換、子窗體工廠),Delphi 的 RegisterClass/GetClass 機制提供了原生的「字符串→類」映射能力,無需巨大的 if-else 或工廠註冊表代碼。

核心機制

  • RegisterClass(AClass: TPersistentClass):將類註冊到全局類表(鍵為類名字符串)。
  • GetClass(const ClassName: string): TPersistentClass:從類表查找並返回類引用。
  • UnRegisterClass:協載時清理(可選)。
  • 要求:類必須繼承自 TPersistent(或其子類),且在 initialization 節註冊。

完整實戰代碼

1. 定義介面與基類

type
  ILog = interface(IUnknown)
    ['{A65044FC-644C-482A-BBFF-50A618835FC6}']
    procedure WriteMessage;
  end;

  TLog = class(TInterfacedPersistent, ILog)
  public
    class function CreateInstance(Name: string): TLog; overload;
    procedure WriteMessage; virtual; abstract;
  end;

2. 具體實現類

TTextLog = class(TLog)
public
  procedure WriteMessage; override; {寫入文本文件}
end;

TXMLLog = class(TLog)
public
  procedure WriteMessage; override; {寫入 XML 文件}
end;

TNullLog = class(TLog)
public
  procedure WriteMessage; override; {空實現}
end;

3. 工廠方法:字符串動態創建

class function TLog.CreateInstance(Name: string): TLog;
var
  AClass: TPersistentClass;
begin
  Result := nil;
  AClass := GetClass(Name); {查找類}
  if Assigned(AClass) then begin
    Result := AClass.NewInstance as TLog; {分配實例}
    Result.Create; {調用構造函數}
  end else
    {錯誤處理: 記錄日誌、拋出異常、返回 NullLog 等}
end;

4. 註冊與使用

initialization
  RegisterClass(TTextLog);
  RegisterClass(TXMLLog);
  RegisterClass(TNullLog);

finalization
  UnRegisterClass(TTextLog);
  UnRegisterClass(TXMLLog);
  UnRegisterClass(TNullLog);

5. 調用示例

procedure TForm1.Button1Click(Sender: TObject);
var Log: TLog;
begin
  {實際可從配置文件讀取 'TXMLLog' }
  Log := TLog.CreateInstance('TXMLLog');
  if Assigned(Log) then begin
    Log.WriteMessage;
    Log.Free;
  end;
end;

進階應用模式

1. 配置驅動插件加載

{INI 文件}
[Logger]
ClassName=TXMLLog

{讀取並創建}
var LogClass: string;
LogClass := IniFile.ReadString('Logger', 'ClassName', 'TTextLog');
Log := TLog.CreateInstance(LogClass);

2. 算法策略模式

type
  TSortAlgorithm = class(TInterfacedPersistent)
  public procedure Execute(List: TStrings); virtual; abstract; end;

TQuickSort = class(TSortAlgorithm) ... end;
TMergeSort = class(TSortAlgorithm) ... end;
TBubbleSort = class(TSortAlgorithm) ... end;

{運行時切換}
Algorithm := TSortAlgorithm.CreateInstance(Config.SortMethod);
Algorithm.Execute(DataList);

3. 子窗體動態創建

var FormClass: TFormClass;
FormClass := TFormClass(GetClass('T' + ModuleName + 'Form'));
if Assigned(FormClass) then
  FormClass.Create(Application).Show;

注意事項

  • 類名唯一性:全項目範圍內類名不可重複,建議加模塊前綴(如 TLogger_Text)。
  • RTTI 依賴:RegisterClass 需類編譯時包含 RTTI({$M+} 或繼承 TPersistent 默認開啟)。
  • 包裝單元:動態加載包 (BPL) 時,需在包的 initialization 註冊,主程式調用 LoadPackage 後方可 GetClass。
  • 嚴格私有:Delphi 2009+ 引入 strict private/strict protected,真正限制單元外訪問,配合 RegisterClass 更安全。

總結

RegisterClass/GetClass 是 Delphi 原生的輕量級依賴注入/工廠基礎設施,零第三方庫、零配置文件、極簡代碼即可實現「字符串動態實例化」,是構建插件系統、策略模式、多文檔界面 (MDI) 窗體管理的利器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved