我会自己回答这个问题,但如果你比我快,或者不喜欢我的解决方案,请随时提供你的答案.我只是想出了这个想法,并希望对此有一些看法.
目标:一种可读的配置类(如INI文件),但不必写入(并且在添加了新的配置项之后进行调整)加载和保存方法.
我想创建一个类
TMyConfiguration = class (TConfiguration) ... property ShowFlags : Boolean read FShowFlags write FShowFlags; property NumFlags : Integer read FNumFlags write FNumFlags; end;
调用TMyConfiguration.Save(继承自TConfiguration)应该创建一个文件
[Options] ShowFlags=1 NumFlags=42
问题:最好的方法是什么?
解决方法
这是我提出的解决方案.
我有一个基础课
TConfiguration = class protected type TCustomSaveMethod = function (Self : TObject; P : Pointer) : String; TCustomLoadMethod = procedure (Self : TObject; const Str : String); public procedure Save (const FileName : String); procedure Load (const FileName : String); end;
procedure TConfiguration.Load (const FileName : String); const PropNotFound = '_PROP_NOT_FOUND_'; var IniFile : TIniFile; Count : Integer; List : PPropList; TypeName,PropName,InputString,MethodName : String; LoadMethod : TCustomLoadMethod; begin IniFile := TIniFile.Create (FileName); try Count := GetPropList (Self.ClassInfo,tkProperties,nil) ; GetMem (List,Count * SizeOf (PPropInfo)) ; try GetPropList (Self.ClassInfo,List); for I := 0 to Count-1 do begin TypeName := String (List [I]^.PropType^.Name); PropName := String (List [I]^.Name); InputString := IniFile.ReadString ('Options',PropNotFound); if (InputString = PropNotFound) then Continue; MethodName := 'Load' + TypeName; LoadMethod := Self.MethodAddress (MethodName); if not Assigned (LoadMethod) then raise EConfigLoadError.Create ('No load method for custom type ' + TypeName); LoadMethod (Self,InputString); end; finally FreeMem (List,Count * SizeOf (PPropInfo)); end; finally FreeAndNil (IniFile); end;
基类可以为delphi默认类型提供加载和保存方法.然后,我可以为我的应用程序创建一个配置,如下所示:
TMyConfiguration = class (TConfiguration) ... published function SaveTObject (P : Pointer) : String; procedure LoadTObject (const Str : String); published property BoolOption : Boolean read FBoolOption write FBoolOption; property ObjOption : TObject read FObjOption write FObjOption; end;
function TMyConfiguration.SaveTObject (P : Pointer) : String; var Obj : TObject; begin Obj := TObject (P); Result := Obj.ClassName; // does not make sense; only example; end;