zoukankan      html  css  js  c++  java
  • 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对象,负责模块的管理,进行模块管理类的构造函数

    这里创建了一个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开发教程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)

  • 相关阅读:
    安装future包,django-crispy-forms
    django学习笔记(七)-----视图
    django学习笔记(六)-----模型
    django学习笔记(五)------path
    django学习笔记(四)---基本流程三(视图,模板基本使用)
    django学习笔记(三)--基本流程二---admin站点管理
    django学习笔记(二)基本流程一
    C#时间
    可空类型的DateTime转换成字符串
    asp.net mvc Razor一点小注意点
  • 原文地址:https://www.cnblogs.com/erp-system/p/4222630.html
Copyright © 2011-2022 走看看