What is the best way to serialize Delphi application configuration?

后端 未结 7 1734
猫巷女王i
猫巷女王i 2021-02-02 02:21

I will answer this question myself, but feel free to provide your answers if you are faster than me or if you don\'t like my solution. I just came up with this idea and would li

7条回答
  •  闹比i
    闹比i (楼主)
    2021-02-02 03:00

    This is my proposed solution.

    I have a base class

    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;
    

    The Load methods look like this (Save method accordingly):

    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, tkProperties, List);
          for I := 0 to Count-1 do
            begin
            TypeName  := String (List [I]^.PropType^.Name);
            PropName  := String (List [I]^.Name);
            InputString := IniFile.ReadString ('Options', PropName, 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;
    

    The base class could provide load and save methods for the delphi default types. I can then create a configuration for my application like this:

    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;
    

    Example of a custom save method:

    function TMyConfiguration.SaveTObject (P : Pointer) : String;
    var
      Obj : TObject;
    begin
      Obj := TObject (P);
      Result := Obj.ClassName;  // does not make sense; only example;
    end;       
    

提交回复
热议问题