从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对象,负责模块的管理,进行模块管理类的构造函数
这里创建了一个TObjectList 对象,该对象用于保存模块列表。
TSingletonFactory.Create(IRegistry,@CreateRegObj);几行是类厂的创建,这部分在接口管理里详细介绍。
继续执行,当所有包含initialization部分的单元执行过后,就到了程序入口
进入这几个函数看一下
可以看出,其实TTangramApp只是起了几个同名函数,实际调用还是交给了Forms的Application对象,使得主程序在启动之前有机会进行一些初始化工作
接下来运行到Run函数
FLoadModuleFromRegistry 在构造函数里已经设置为True,而我们没有修改这个属性,所以在这里开始进行模块的自动加载
这里调用模块管理类TModuleMgr对象FModuMgr进行模块加载,进入LoadModules
GetModuleList函数负责从XML文件读取需要自动加载的模块文件路径,保存到aList
这里先是判断文件是否存在,如果存在则准备加载
这里根据模块的文件创建一个TTangramModule对象,用于负责模块的加载
这里判断模块的类型然后进行加载,加载完成后
@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;
当所有模块加载完成后,开始进行模块初始化
这里取出模块对象列表FModuleList里的每一个对象进行初始化
注意这里的 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开发教程02 http://pan.baidu.com/s/11xN5s
框架源代码下载地址 http://pan.baidu.com/s/1jGIc2Su
DEMO源代码下载地址 http://pan.baidu.com/s/1bnyEafH
联系QQ:1330009208 (验证信息请填ERPSYSTEM)