為每種需要傳遞的參數去定義一個TSerialableComponent,也是比較麻煩,用Key/Value的字典更簡潔。
TStringList就是一個可以作為Key/Value來使用的字典,通過Values(Key)函數來讀寫值,通過Text屬性來序列化和還原序列化。但是對複雜資料,如Byte Array,可能會遇到麻煩。
下面是自己實現的一個Dictionary,可序列化和還原序列化:
TKeyValueList=class private FList:TacroHashList; function GetCount: integer; function _Clear(AUserData: Pointer; const AStr: string; var APtr: Pointer): Boolean; function _Serialize(AUserData: Pointer; const AStr: string; var APtr: Pointer): Boolean; public procedure Add(Key:string;Value:Variant); procedure Delete(Key:string); function TryGetValue(Key:string;out Value:Variant):Boolean; function GetValue(Key:string):Variant; procedure Clear;virtual; public constructor Create(ACapacity:integer=256);virtual; destructor Destroy;override; property Count:integer read GetCount; public //序列化成Byte Array function SerializeToVariant:Variant;virtual; procedure UnSerializeFromVariant(AData:Variant);virtual; end;{ TKeyValueList }procedure TKeyValueList.Add(Key: string; Value: Variant);var P:PVariant;begin if FList.Find(Key,P) then P^:=Value else begin New(P); P^:=Value; FList.Add(Key,P); end;end;procedure TKeyValueList.Clear;begin FList.IterateMethod(nil,_Clear); FList.Clear;end;constructor TKeyValueList.Create(ACapacity: integer);begin inherited Create; FList:=TacroHashList.Create(GetMinPrime(ACapacity),StrCompare,StrHash);end;procedure TKeyValueList.Delete(Key: string);var P:PVariant;begin if FList.Find(Key,P) then begin Dispose(P); FList.Remove(Key); end;end;destructor TKeyValueList.Destroy;begin Clear; FList.Free; inherited;end;function TKeyValueList.GetCount: integer;begin Result:=FList.Count;end;function TKeyValueList.GetValue(Key: string): Variant;var P:PVariant;begin if not FList.Find(Key,P) then raise Exception.CreateFmt('Not found key "%s".',[Key]); Result:=P^;end;function TKeyValueList.SerializeToVariant: Variant;var MS:TMemoryStream; vW:TVariantWriter;begin MS:=TMemoryStream.Create; vW:=TVariantWriter.Create(MS); try FList.IterateMethod(vW,_Serialize); Result:=MemoryToVariant(MS); finally vW.Free; MS.Free; end;end;function TKeyValueList.TryGetValue(Key: string; out Value: Variant): Boolean;var P:PVariant;begin Result:=FList.Find(Key,P); if P<>nil then Value:=P^;end;procedure TKeyValueList.UnSerializeFromVariant(AData: Variant);var MS:TMemoryStream; R:TVariantReader; Key:string; Value:Variant;begin MS:=TMemoryStream.Create; R:=TVariantReader.Create(MS); try VariantToMemory(AData,MS); FList.Clear; MS.Position:=0; while MS.Position<MS.Size do begin Key:=R.ReadVariant; Value:=R.ReadVariant; Add(Key,Value); end; finally R.Free; MS.Free; end;end;function TKeyValueList._Clear(AUserData: Pointer; const AStr: string; var APtr: Pointer): Boolean;begin Dispose(PVariant(APtr));end;function TKeyValueList._Serialize(AUserData: Pointer; const AStr: string; var APtr: Pointer): Boolean;var W:TVariantWriter; P:PVariant;begin Result:=true; W:=TVariantWriter(AUserData); P:=APtr; W.WriteVariant(AStr); W.WriteVariant(P^);end;