Delphi 信息化管理系统开源框架 @ 启动时刻

这篇文章首先走马观花了解一下程序启动那一刻都做了些什么

 1 Program StarOfficeMain;
 2
 3 uses
 4   StarOfficeApplication,
 5   MainForm in ‘Form\MainForm.pas‘ {frmMain},
 6   StarMainFormInterface in ‘Interface\StarMainFormInterface.pas‘;
 7
 8 {$R *.res}
 9
10 begin
11   ReportMemoryLeaksOnShutdown:=True;
12   Application.Initialize;
13   Application.MainFormOnTaskbar := True;
14   Application.CreateForm(TfrmMain, frmMain);
15   Application.Run;
16 end.

这是主程序的工程文件,和默认工程相比,是把原本的Forms替换成StarOfficeApplication

1 unit StarOfficeApplication;
2
3 var
4   Application:TStarOfficeApplication;

StarOfficeApplication定义了一个TStarOfficeApplication对象的全局变量Application,所以替换了Forms的Application

1 constructor TStarOfficeApplication.Create;
2 begin
3   FModuleMgr:=TStarModuleManager.Create;
4 end;

TStarOfficeApplication构造函数里创建了一个TStarModuleManager对象,该对象负责框架的模块管理

1 procedure TStarOfficeApplication.Run;
2 begin
3   Forms.Application.Run;
4   FModuleMgr.final;
5 end;

当工程文件里执行Application.Run的时候,实际调用的是TStarOfficeApplication的Run函数

Run函数首先是调用了Forms文件里的 Application.Run;使程序运行起来

但程序退出时FModuleMgr.final;是对模块的卸载

1 constructor TStarModuleManager.Create;
2 begin
3   FLoadBatch:=‘‘;
4   FModuleList := TObjectList.Create(True);
5   TStarObjectFactoryExt.Create([IStarModuleInfoEnum,IStarModuleLoader], self);
6 end;

模块管理类TStarModuleManager构造函数里注册了一个IStarModuleLoader接口实例对象

TStarObjectFactoryExt实例扩展工厂继承自TStarBaseFactoryExt,在TStarBaseFactoryExt的构造函数里

创建了类厂管理对象FFactoryManager

 1 constructor TStarBaseFactoryExt.Create(const IIDs: array of TGUID);
 2 var i:Integer;
 3 begin
 4   FIIDList:=TStringList.Create;
 5
 6   for i:=low(IIDs) to high(IIDs) do
 7   begin
 8     if StarOfficeFactory.Exists(IIDs[i]) then
 9       Raise Exception.CreateFmt(Err_IntfExists,[GUIDToString(IIDs[i])]);
10
11     FIIDList.Add(GUIDToString(IIDs[i]));
12   end;
13   StarOfficeFactory.RegisterFactory(self);
14 end;
1 function StarOfficeFactory:TStarFactoryManager;
2 begin
3   if FFactoryManager=nil then
4     FFactoryManager:=TStarFactoryManager.Create;
5
6   Result:=FFactoryManager;
7 end;

从代码可以看出,不管何时调用StarOfficeFactory函数,只会在首次调用创建一个类厂管理对象

同理,通知管理,事件管理也在程序启动之时被创建,并添加到类厂管理对象中

 1 procedure TfrmMain.FormCreate(Sender: TObject);
 2 var Intf: IStarModuleLoader;
 3 begin
 4   TStarObjectFactory.Create(IStarMainForm,Self);;
 5
 6   Intf:=StarOffice as IStarModuleLoader;
 7   Intf.LoadBegin;
 8   Intf.LoadModulesFromDir;
 9   Intf.LoadFinish;
10
11   (StarOffice as IStarEventManager).EnumEvent(Self);
12 end;
1 function StarOffice: IInterface;
2 begin
3   if not Assigned(FSysService) then
4     FSysService := TStarOfficeService.Create;
5
6   Result := FSysService;
7 end;

StarOffice 返回的是一个IInterface对象,该对象由TStarOfficeService类创建

StarOffice返回的IInterface对象并没有与接口IStarModuleLoader有任何继承关系,可为什么可以 as 呢?

这是接口的特性之接口查询

1 TStarOfficeService = class(TObject, IInterface)
2   private
3     FRefCount: Integer;
4   protected
5     function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
6     function _AddRef: Integer; stdcall;
7     function _Release: Integer; stdcall;
8   public
9   end;

TStarOfficeService 类实现了IInterface的接口函数

 1 function TStarOfficeService.QueryInterface(const IID: TGUID; out Obj): HResult;
 2 var
 3   aFactory: TStarFactory;
 4 begin
 5   Result := E_NOINTERFACE;
 6   if self.GetInterface(IID, Obj) then
 7     Result := S_OK
 8   else
 9   begin
10     aFactory := StarOfficeFactory.FindFactory(IID);
11     if Assigned(aFactory) then
12     begin
13       aFactory.CreateInstance(IID, Obj);
14       Result := S_OK;
15     end;
16   end;
17 end;

当对一个接口对象进行 as 操作时就会调用 QueryInterface 函数,这是接口的机制

首先会调用默认的GetInterface函数进行接口查询,GetInterface会从继承关系中查找接口,当找不到时再从接口工厂中寻找接口工厂

如果找到了就通过相应工厂创建接口实例对象

这就是统一接口调用的原理

回到主程序的窗体创建函数,调用了IStarModuleLoader接口的LoadModulesFromDir函数,该接口函数实现了将当前程序目录下的模块全部加载进来

(StarOffice as IStarEventManager).EnumEvent(Self);

则调用了事件管理接口的事件枚举函数,将所有注册到事件管理的事件枚举出来并依此动态创建菜单

这就是DEMO程序的启动时刻

时间: 2024-10-11 13:16:34

Delphi 信息化管理系统开源框架 @ 启动时刻的相关文章

Delphi下IOCP开源框架:DIOCP 成功应用案例分享

首先说明,该项目不是本人的项目,本文转自盒子. 该项目使用的DIOCP版本为1.0,目前diocp为3.5 以下是盒子的原文 ------------------------------------------------------------------------------ DIOCP是Delphi下进行IOCP服务端通讯开发的一个非常好的开源框架,稳定.高效并且使用起来十分简单.     自己两个多月之前因为需要使用Delphi开发一个TCP服务端,当时也是到处爬文,希望找到一个稳定且

吉特仓库管理系统(开源)-如何在网页端启动WinForm 程序

原文:吉特仓库管理系统(开源)-如何在网页端启动WinForm 程序 在逛淘宝或者使用QQ相关的产品的时候,比如淘宝我要联系店家点击旺旺图标的时候能够自动启动阿里旺旺进行聊天.之前很奇怪为什么网页端能够自动启动客户端程序,最近在开发吉特仓储管理系统的时候也遇到一个类似的问题,因为使用网页端的打印效果并不是太好,之前也写过关于打印相关的文章可以查阅,我需要使用WinForm客户端来驱动打印,但是我又不想重新开发Winform客户端的所有功能,只要能够使用winform驱动打印即可.我就需要一个类似

开源框架(整理)

开源框架(整理) Json.NET http://json.codeplex.com/ Json.Net 是一个读写Json效率比较高的.Net框架.Json.Net 使得在.Net环境下使用Json更加简单.通过Linq To JSON可以快速的读写Json,通过JsonSerializer可以序列化你的.Net对象.让你轻松实现.Net中所有类型(对象,基本数据类型 等)和Json的转换. Math.NET http://www.mathdotnet.com/ Math.NET的目标是为提供

浅析国产开源框架Guns的使用及注意事项

前几天在做一个后台管理系统.于是上网找了一下有没有快速搭建后台管理系统的,在码云上看到了一个国产的开源框架,Guns,感觉很好,在配置的时候出现了一些问题,在网上找了一些都没有找到.于是想写下来,我在使用的时候遇到的问题及解决方法,好了下面就让我来介绍一下这款开源的框架 首先说一下Guns的架构  前端使用了Bootstrap v3.3.6 + jQuery v2.1.4 + bootstrap-table v1.11.1 + layer v2.1 + zTree core v3.5.28 +

《开源框架那点事儿25》:对框架模板引擎实现方式的改造实录

点滴悟透设计思想,Tiny模板引擎优化实录! 增加框架设计兴趣小组:http://bbs.tinygroup.org/group-113-1.html Tiny模板引擎的实现方式原来是採用的编译方式,近期发生了一些问题.因此我认为有必要把编译方式调整为解释方式,为此就開始了此次实现活动. 编译方式存在的问题 当时採用编译方式.主要是考虑到编译方式在执行时不必再去遍历语法树.因此就採用了编译方式. 可是在实际应用其中,出现了例如以下问题: 文件路径冲突的问题 因为採用的是编译方式,这个时候就存在在

iOS开发-常用第三方开源框架介绍(你了解的ios只是冰山一角)

iOS开发-常用第三方开源框架介绍(你了解的ios只是冰山一角) 2015-04-05 15:25 2482人阅读 评论(1) 收藏 举报开源框架 图像: 1.图片浏览控件MWPhotoBrowser       实现了一个照片浏览器类似 iOS 自带的相册应用,可显示来自手机的图片或者是网络图片,可自动从网络下载图片并进行缓存.可对图片进行缩放等操作.      下载:https://github.com/mwaterfall/MWPhotoBrowser目前比较活跃的社区仍旧是Github,

基于Doubango的iOS客户端开源框架

一.ios-ngn-statck工程 1.Tests ---功能测试 2.底层模块(c和c++) Doubango --- 基于3GPP IMS/RCS 并能用于嵌入式和桌面系统的开源框架 1) tinyWRAP --- c++代码,对c代码以面向面向对象的方式进行封装,提供给上层调用. 2) tinyDAV --- Doubango媒体音频/视频控制,tinyMedia核心框架 a) audio --- 音频 b) codecs --- 编解码器 c) msrp --- 文件传输 d)vide

《开源框架那点事儿23》:采用TinyDB组件方式开发

采用TinyDB组件方式开发 步骤 Icon 前文介绍四则运算的流程编程开发时,说过流程编排在开发重复功能时,可以利用已有的组件库快速开发.对于开发人员而言只需要简单配置流程就可以完成工作了. 开发增删改查的组件接口.本来这部分很花费时间,如果采用组件复用的话,就可以实现一次开发,终生受益. 配置curd.beans.xml和tinydb.xml. 使用流程编辑器定制组件流程curd.pageflow. 修改页面文件:list.page和operate.page,使之符合流程方式调用. 修改布局

分布式计算开源框架Hadoop入门实践(一)

在SIP项目设计的过程中,对于它庞大的日志在开始时就考虑使用任务分解的多线程处理模式来分析统计,在我从前写的文章<Tiger Concurrent Practice --日志分析并行分解设计与实现>中有所提到.但是由于统计的内容暂时还是十分简单,所以就采用Memcache作为计数器,结合MySQL就完成了访问控制以及统计的工作.然而未来,对于海量日志分析的工作,还是需要有所准备.现在最火的技术词汇莫过于“云计算”,在Open API日益盛行的今天,互联网应用的数据将会越来越有价值,如何去分析这