ERPSYSTEM开发教程04 框架模块管理

从DEMO程序获知,

框架主程序工程文件里Forms替换为uTangramFramework,

每个模块都有一个TModule子类和一个GetModuleClass导出函数

那么框架是如何进行模块管理的呢?

我们先从模块入手

 

unit DllOnePlugin;

interface

uses SysUtils,Classes,uTangramModule,SysModule,RegIntf;

Type
  TUserModule=Class(TModule)
  private 
  public 
    Constructor Create; override;
    Destructor Destroy; override;

    procedure Init; override;
    procedure final; override;
    procedure Notify(Flags: Integer; Intf: IInterface); override;

    class procedure RegisterModule(Reg:IRegistry);override;
    class procedure UnRegisterModule(Reg:IRegistry);override;
  End;

implementation

initialization
  RegisterModuleClass(TUserModule);
finalization

end.

 

这是模块的TModule子类,initialization下方的代码是被最先执行的,我们看一下RegisterModuleClass函数放在uTangramModule.pas

 

unit uTangramModule;
{$weakpackageunit on}
interface

uses SysUtils,RegIntf,SysModule;

procedure InstallModule(Reg:IRegistry);
procedure UnInstallModule(Reg:IRegistry);
function GetModuleClass:TModuleClass;

Exports
  InstallModule,
  UnInstallModule,
  GetModuleClass;

implementation

var FModuleClass:TModuleClass;

procedure RegisterModuleClass(ModuleClass:TModuleClass);
begin
  FModuleClass:=ModuleClass;
end;

function GetModuleClass:TModuleClass;
begin
  Result:=FModuleClass;
end;

end.

RegisterModuleClass(TUserModule);其实就是将模块里的TModule子类保存到一个类引用变量FModuleClass

而导出函数GetModuleClass则返回的FModuleClass,因此通过导出函数GetModuleClass就可以获得模块的TModule子类

 

接下来我们看主程序

Forms替换为uTangramFramework,而uTangramFramework文件里定义了一个Application对象,也就是说

Program HOST;

uses
  uTangramFramework,
  MainForm in 'MainForm.pas' {FrmMain};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TFrmMain, FrmMain);
  Application.Run;
end.

这里的Application对象其实由uTangramFramework里定义的

unit uTangramFramework

TTangramApp=Class

var
  Application:TTangramApp;

initialization
  Application:=TTangramApp.Create;
finalization
  Application.Free;

这样,程序启动之初就会创建由框架定义的Application对象,接下来我们就从这行代码开始,进行调试,看模块是如何被管理的

首先进入TangramApp构造函数

这里的 FLoadModuleFromRegistry 是TTangramApp的 LoadModuleFromRegistry 属性变量,设置框架默认是从XML进行模块加载

而FModuleMgr是一个TModuleMgr对象,负责模块的管理,进行模块管理类的构造函数

ERPSYSTEM开发教程04 框架模块管理_第1张图片

这里创建了一个TObjectList 对象,该对象用于保存模块列表。

TSingletonFactory.Create(IRegistry,@CreateRegObj);几行是类厂的创建,这部分在接口管理里详细介绍。

继续执行,当所有包含initialization部分的单元执行过后,就到了程序入口

ERPSYSTEM开发教程04 框架模块管理_第2张图片

进入这几个函数看一下

可以看出,其实TTangramApp只是起了几个同名函数,实际调用还是交给了Forms的Application对象,使得主程序在启动之前有机会进行一些初始化工作

接下来运行到Run函数

ERPSYSTEM开发教程04 框架模块管理_第3张图片

FLoadModuleFromRegistry 在构造函数里已经设置为True,而我们没有修改这个属性,所以在这里开始进行模块的自动加载

这里调用模块管理类TModuleMgr对象FModuMgr进行模块加载,进入LoadModules

ERPSYSTEM开发教程04 框架模块管理_第4张图片

GetModuleList函数负责从XML文件读取需要自动加载的模块文件路径,保存到aList

这里先是判断文件是否存在,如果存在则准备加载

ERPSYSTEM开发教程04 框架模块管理_第5张图片

这里根据模块的文件创建一个TTangramModule对象,用于负责模块的加载

ERPSYSTEM开发教程04 框架模块管理_第6张图片

ERPSYSTEM开发教程04 框架模块管理_第7张图片

这里判断模块的类型然后进行加载,加载完成后

  @GetModuleClassPro := GetProcAddress(FModuleHandle, 'GetModuleClass');
  if Assigned(GetModuleClassPro) then
  begin
    FModuleCls:=GetModuleClassPro;
    FValidModule:=FModuleCls<>nil;
    if (FModuleCls<>nil) and (CreateModuleObjInstance) then
      FModuleObj:=FModuleCls.Create;
  end;

获得模块的导出函数GetModuleClass,如果存在这个函数则保存并调用,将返回值保存到FModuleCls,这个FModuleCls保存的就是模块里的TModule子类,并创建对象

procedure TModuleMgr.LoadModuleFromFile(const ModuleFile: string);
var Module:TTangramModule;
begin
  try
    Module:=TTangramModule.Create(ModuleFile,self.FLoadBatch);
    if Module.IsValidModule then FModuleList.Add(Module) else Module.Free;
  Except
    on E: Exception do
    begin
      WriteErrFmt(Err_LoadModule, [ExtractFileName(ModuleFile), E.Message]);
    end;
  end;
end;

如果是一个有效模块,则添加到对象列表FModuleList

procedure TTangramApp.Run;
begin
  if FLoadModuleFromRegistry then
  begin
    FModuleMgr.LoadModules;
    FModuleMgr.Init; end;
  Forms.Application.Run;
  FModuleMgr.final;
end;

当所有模块加载完成后,开始进行模块初始化

ERPSYSTEM开发教程04 框架模块管理_第8张图片

这里取出模块对象列表FModuleList里的每一个对象进行初始化

ERPSYSTEM开发教程04 框架模块管理_第9张图片

注意这里的  FModuleObj.Init FModuleObj是一个TModule对象,是在模块加载时调用GetModuleClass返回模块里的TModule子类创建的对象,

而Init在TModule里是虚函数,所以这里实际调用的实际是模块里的TModule子类实现的Init函数

当所有模块都初始化过后就进入消息循环,直到主窗体退出则调用模块的终止化函数

procedure TTangramApp.Run;
begin
  if FLoadModuleFromRegistry then
  begin
    FModuleMgr.LoadModules;
    FModuleMgr.Init;
  end;
  Forms.Application.Run;
  FModuleMgr.final;
end;

TModuleMgr提供了两个接口IModuleLoader,IModuleInstall,提供给开发者进行自定义模块加载安装

 

视频教程地址:

ERPSYSTEM开发教程01     http://pan.baidu.com/s/1kT7Rb3D

ERPSYSTEM开发教程02     http://pan.baidu.com/s/11xN5s

框架源代码下载地址            http://pan.baidu.com/s/1jGIc2Su

DEMO源代码下载地址         http://pan.baidu.com/s/1bnyEafH

联系QQ:1330009208 (验证信息请填ERPSYSTEM)

你可能感兴趣的:(System)