gpt4 book ai didi

delphi - Delphi中如何设计一个界面来保存不同的集合?

转载 作者:行者123 更新时间:2023-12-03 18:35:22 29 4
gpt4 key购买 nike

我有多个集合,例如:

TFooList = TObjectDictionary<string,TFoo>;
TBarList = TObjectDictionary<string,TBar>;
....

TRoot = class
value : string
end;

TFoo = class(TRoot)
...
end;

TBar = class(TRoot)
...
end;

我有一个可以保存或加载集合的接口(interface)/类:
ISave = interface
procedure Save( TDictionary<string, string> );
function Load: TDictionary<string, string>;
end;

请注意,该接口(interface)需要一个键/字符串对集合才能正常工作。

我实现了一些 ISave 类,以便在文件或数据库中加载/保存集合:
TDbSave = class( TInterfacedObject , ISave )
....
end;
iSave := TDbSave( ConnString )

TFileSave = class( TInterfacedObject , ISave )
....
end;
iSave := TFileSave( fileName );

因此,最后一 block 将从每个集合继承并创建保存/加载方法以将每个集合“翻译”成/来自 TDictionary(string, string)
    TFooListSavable = TFooList;
procedure Create( save_load : ISave );
procedure Save;
procedure Load;
....
end;

procedure TFooListSavable.Save
// 1. create a TDictionary<string, string>
// 2. load the dictionary above with my collection translating
// each Foo object into a string
// 3. call save_load.Save( dictionary );
end;
procedure TFooListSavable.Load
// 1. create a TDictionary<string, string>
// 2. call save_load.load to load it
// 3. Move over the collection and translate string into TFoo and
// 4. AddOrEquals each TFoo created into TFooListSavable.
end;

所以,我对这种方法有两个问题:

1) 保存或加载的接口(interface)需要集合中的字符串值,虽然每个集合中的所有对象都继承自定义了该字符串的类,但我不知道如何转换像 TDictionary<string,TFoo> 这样的集合变成 TDictionary<string,string>无需求助于上面的代码(这将复制集合以将其传递给 iSave 对象)。

2)我觉得,虽然可以替换 iSave对象更改保存/加载集合的方式而不更改集合本身,我不知道这是否是保存/加载保留相关对象的集合的最佳方法。

最佳答案

我认为你正在以错误的方式解决这个问题。
ISave不应该有任何TDictionary的概念一点也不。它应该只公开读取/写入基本数据类型(整数、字符串等)的方法。让 TFooListSavableTBarListSavable决定如何序列化它们各自的TDictionary数据随心所欲,调用 ISave根据需要的方法。

如果 TFooListSavable 会更好和 TBarListSavable通过ISave给每个人TFoo/TBar并让他们直接序列化自己的数据成员。

例如,像这样:

type
ISerialize = interface
function HasData: Boolean;
procedure StartWriteCollection;
procedure StartWriteItem;
procedure FinishWriteCollection;
procedure FInishWriteItem;
procedure WriteBoolean(value: Boolean);
procedure WriteInteger(value: Integer);
procedure WriteString(const value: String);
...
procedure StartReadCollection;
procedure StartReadItem;
procedure FinishReadCollection;
procedure FinishReadItem;
function ReadBoolean: Boolean;
function ReadInteger: Integer;
function ReadString: String;
...
end;

TRoot = class
public
value : string;
constructor Create; virtual;
procedure Save(Dest: ISerialize); virtual;
procedure Load(Src: ISerialize); virtual;
end;

TBaseList<T: TRoot, constructor> = class(TObjectDictionary<string, T>)
public
procedure Save(Dest: ISerialize);
procedure Load(Src: ISerialize);
end;

TFoo = class(TRoot)
public
myint: Integer;
...
procedure Save(Dest: ISerialize); override;
procedure Load(Src: ISerialize); override;
end;
TFooList = TBaseList<TFoo>;

TBar = class(TRoot)
mybool: Boolean;
...
procedure Save(Dest: ISerialize); override;
procedure Load(Src: ISerialize); override;
end;
TBarList = TBaseList<TBar>;

TDbSerialize = class(TInterfacedObject, ISerialize)
...
end;

TFileSerialize = class(TInterfacedObject, ISerialize)
...
end;

procedure TBaseList<T>.Save(Dest: ISerialize);
var
pair: TPair<string, T>;
begin
Dest.StartWriteCollection;
for pair in Self do
begin
Dest.StartWriteItem;
Dest.WriteString(pair.Key);
TRoot(pair.Value).Save(Dest);
Dest.FinishWriteItem;
end;
Dest.FinishWriteCollection;
end;

procedure TBaseList<T>.Load(Src: ISerialize);
var
Cnt, I: Integer;
key: string;
value: T;
begin
Self.Clear;
Src.StartReadCollection;
While Src.HasData do
begin
Src.StartReadItem;
key := Src.ReadString;
value := T.Create;
try
value.Load(Src);
Self.Add(key, value);
except
value.Free;
raise;
end;
Src.FinishReadItem;
end;
Src.FinishReadCollection;
end;

procedure TRoot.Save(Dest: ISerialize);
begin
Dest.WriteString(value);
end;

procedure TRoot.Load(Src: ISerialize);
begin
value := Src.ReadString;
end;

procedure TFoo.Save(Dest: ISerialize);
begin
inherited;
Dest.WriteInteger(myint);
end;

procedure TFoo.Load(Src: ISerialize);
begin
inherited;
myint := Src.ReadInteger;
end;

procedure TBar.Save(Dest: ISerialize);
begin
inherited;
Dest.WriteBoolean(mybool);
end;

procedure TBar.Load(Src: ISerialize);
begin
inherited;
mybool := Src.ReadBoolean;
end;

关于delphi - Delphi中如何设计一个界面来保存不同的集合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37713575/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com