界面动态配置:持久化反持久化
界面在可配置的情况下需要读写配置文件,VCL提供了一种方式 TReader 和 TWriter 方式保存界面资源。
object Form1: TForm1 Left = 0 Top = 0 Caption = 'Form1' ...
object lbl1: TLabel Left = 200 Top = 152
... end object btn1: TButton Left = 184 ...
end end
直接存成文本格式资源文件,只要是对象继承于TPersistent所有属性字段都能正常被初始化。同时他内部的子对象通过嵌套方式持久化。
基于这种比较简单的嵌套模式存贮方案。
1、读取配置并生成界面的过程
- 先加载自身的属性信息
- 在加载子模块的配置信息
- 触发界面初始化加载事件
通过上述三步骤实现对类似Delphi界面配置信息的读取。考虑到具体配置文件格式的存储位置和方式交由框架实现因此对其接口化
IViewStore 实现了基本的读写属性值的方式。
IViewStoreAttributs 接口并不是必须的,可以实现也可以不实现。增加这个接口的目的是为同一个地方配置所有需要持久化的属性。可以理解为Publish的公共属TFiler通过RTTI获取所需要持久化的信息,方便在获得所有相关的信息。
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 //1 保存属性 2 /// 3 /// 界面需要保存和还原的的属性信息 4 /// 为了减少复杂度,属性信息竟然不要嵌套 5 IViewStoreAttributs = interface 6 ['{E4C17A34-83AC-4C32-BD18-4C76A9F56D75}'] 7 function GetCount: Integer; stdcall; 8 function GetNames(Index: Integer): WideString; stdcall; 9 function GetValues(Index: Integer): WideString; stdcall; 10 procedure SetValues(Index: Integer; const Value: WideString); stdcall; 11 property Count: Integer read GetCount; 12 property Names[Index: Integer]: WideString read GetNames; 13 property Values[Index: Integer]: WideString read GetValues write SetValues; 14 end; 15 16 //1 界面数据存储 17 /// 18 /// 用于保存界面特有数据信息 19 /// 比如视图位置 20 IViewStore = interface(IInterface) 21 ['{BBC202FA-03D7-4A1F-BB28-13990DB87F1E}'] 22 procedure Clear; stdcall; 23 function Count: Integer; stdcall; 24 procedure Erase(const AName: WideString); stdcall; 25 function Exists(const AName: WideString): Boolean; stdcall; 26 function GetNames(Index: Integer): WideString; stdcall; 27 function GetValueOfIndex(Index: Integer): WideString; stdcall; 28 29 function ReadBool(const AName: WideString; Default: Boolean): Boolean; stdcall; 30 function ReadFloat(const AName: WideString; Default: Double): Double; stdcall; 31 function ReadInteger(const AName: WideString; Default: Longint): LongInt; stdcall; 32 function ReadString(const AName, Default: WideString): WideString; stdcall; 33 procedure WriteBool(const AName: WideString; Value: Boolean); stdcall; 34 procedure WriteFloat(const AName: WideString; Value: Double); stdcall; 35 procedure WriteInteger(const AName: WideString; Value: Longint); stdcall; 36 procedure WriteString(const AName, Value: WideString); stdcall; 37 38 procedure WriteAttribs(const Attribs: IViewStoreAttributs); stdcall; 39 procedure ReadAttribs(const Attribs: IViewStoreAttributs); stdcall; 40 procedure Write(const AName:WideString; out AStore:IViewStore); stdcall; 41 function Read(const AName:wideString; out AStore:IViewStore):Boolean stdcall; 42 43 property Names[Index: Integer]: WideString read GetNames; 44 property ValueOfIndex[Index: Integer]: WideString read GetValueOfIndex; 45 end;
对于模块嵌套考虑
1 procedure WriteAttribs(const Attribs: IViewStoreAttributs); stdcall; 2 procedure ReadAttribs(const Attribs: IViewStoreAttributs); stdcall; 3 procedure Write(const AName:WideString; out AStore:IViewStore); stdcall; 4 function Read(const AName:wideString; out AStore:IViewStore):Boolean stdcall;
使用Write 和 Read 函数获得 IViewStore 这样外部不要考虑接口实例的具体创建方法。
同时对于一些简单的对象只要实现 IViewStoreAttributs 接口,在持久化和初始化的时候不用考虑谁帮你初始化。
相关问题:
如果要实现全自动加载,是否应该加强IViewStoreAttributs 接口就能达到目的?
http://www.cnblogs.com/gleam/archive/2012/12/06/2804933.html