插件管理框架 for Delphi(三)

    技术2022-05-11  100

    1       前言

    2       插件框架(untDllManager

    3       使用举例

    3.1   类图

    3.2   客户端组件

    TDll派生出TClientDll

    根据真实的动态库接口添加相关属性;

    3.2.1    组件定义

    unit untClientDll;

     

    interface

     

    uses

      Windows, Classes, SysUtils, untDllManager, untProcDefine;

     

    type

     

      EClientDllError = Class(Exception);

     

      { TClientDll

        o 继承自 TDll;

        o 自动获取 ClientInitialize 地址并保存在 ClientInitialize 属性中;

        o 自动获取 ClientInsertTrigger 地址并保存在 ClientInsertTrigger 属性中;

      }

     

      TClientDll = Class(TDll)

      private

        FClientInitialize: TClientInitialize;

        FClientInsertTrigger: TClientInsertTrigger;

        FClientGetDescription: TClientGetDescription;

        FClientSetup: TClientSetup;

        FDescription: String;

        FUseTrigger: Bool;

      protected

        procedure DoDllLoaded; override;

        procedure DoDllUnLoaded; override;

      public

        constructor Create; override;

        property ClientGetDescription: TClientGetDescription read FClientGetDescription;

        property ClientInitialize: TClientInitialize read FClientInitialize;

        property ClientInsertTrigger: TClientInsertTrigger read FClientInsertTrigger;

        property ClientSetup: TClientSetup read FClientSetup;

        property Description: String read FDescription write FDescription;

        property UseTrigger: Bool read FUseTrigger write FUseTrigger;

      end;

     

    implementation

     

    { TClientDll }

     

    constructor TClientDll.Create;

    begin

      inherited;

      FClientInitialize := nil;

      FClientInsertTrigger := nil;

      FClientGetDescription := nil;

      FClientSetup := nil;

    end;

     

    procedure TClientDll.DoDllLoaded;

    begin

      FClientInitialize := GetProcAddress(csClientInitialize);

      if not Assigned(FClientInitialize) then

        raise EClientDllError.Create('No found of Proc "ClientInitialize".');

      FClientInsertTrigger := GetProcAddress(csClientInsertTrigger);

      if not Assigned(FClientInsertTrigger) then

        raise EClientDllError.Create('No found of Proc "ClientInsertTrigger".');

      //可选接口,即使不存在也不报错。

      FClientGetDescription := GetProcAddress(csClientGetDescription);

      FClientSetup := GetProcAddress(csClientSetup);

      inherited;

    end;

     

    procedure TClientDll.DoDllUnLoaded;

    begin

      inherited;

      FClientInitialize := nil;

      FClientInsertTrigger := nil;

      FClientGetDescription := nil;

      FClientSetup := nil;

    end;

     

    end.

     

    3.2.2    组件使用

    procedure TXXXXServer.LoadClientDll(const FileName: String);

    //功能:加载一个ClientDll,并将相关数据传递进去

    var

      Index: Integer;

      Description: String;

      UseTrigger: Bool;

      AClientDll: TClientDll;

    begin

      Index := FClientDlls.Add(FileName);

      if Index < 0 then

        raise EXXXXError.CreateFmt('ClientDll "%s" 之前已经装载.', [FileName]);

      //尝试读取地址

      try

        FClientDlls[Index].Loaded := True;

      finally

        if not FClientDlls[Index].Loaded then

          FClientDlls[Index].Free;

      end;

      //初始化该Client,同时将相关信息传入

      UseTrigger := False;

      AClientDll := TClientDll(FClientDlls[Index]);

      if Assigned(AClientDll.ClientSetup) then

        AClientDll.ClientSetup(mscAppPath + 'Client/', False);

    end;

    3.3   服务端组件

    3.3.1    组件定义

    unit untServerDll;

     

    interface

     

    uses

      Windows, Classes, SysUtils, untDllManager, untProcDefine;

     

    type

     

      EServerDllError = Class(Exception);

     

      { TServerDll

        o 继承自 TDll;

        o 自动获取 QueryInterface 地址并保存在QueryInterface属性中;

      }

     

      TServerDll = Class(TDll)

      private

        FFunctions: TObject;

        FQueryInterface: TProcQueryInterface;

      protected

        procedure DoDllLoaded; override;

        procedure DoDllUnLoaded; override;

      public

        procedure RefreshAllFunctionsPermit;

        property Functions: TObject read FFunctions write FFunctions;

        property QueryInterface: TProcQueryInterface read FQueryInterface;

      end;

     

    implementation

     

    uses

      untFunctionProc;

     

    { TServerDll }

     

    procedure TServerDll.DoDllLoaded;

    begin

      FQueryInterface := GetProcAddress(csQueryInterface);

      if not Assigned(FQueryInterface) then

        raise EServerDllError.Create('No found of "QueryInterface" Proc.');

      inherited; //此句需要放在后面

    end;

     

    procedure TServerDll.DoDllUnLoaded;

    begin

      inherited;

      FQueryInterface := nil;

    end;

     

    procedure TServerDll.RefreshAllFunctionsPermit;

    var

      I: Integer;

    begin

      Assert(FFunctions <> nil);

      for I := 0 to TFunctionList(FFunctions).Count - 1 do

        if TFunction(TFunctionList(FFunctions)[I]).Dll = Self then

          TFunction(TFunctionList(FFunctions)[I]).Permit := Permit;

    end;

     

    end.

     

    3.3.2    组件使用

    略。

    [文终]

     

     


    最新回复(0)