如何在Delphi中设计一个界面来保存不同的集合?
我有多个收藏,如:如何在Delphi中设计一个界面来保存不同的集合?,delphi,collections,interface,Delphi,Collections,Interface,我有多个收藏,如: TFooList = TObjectDictionary<string,TFoo>; TBarList = TObjectDictionary<string,TBar>; .... TRoot = class value : string end; TFoo = class(TRoot) ... end; TBar = class(TRoot) ... end; 因此,最后一部分将从每个集合继承,并创建save/load方法,将每个集合“
TFooList = TObjectDictionary<string,TFoo>;
TBarList = TObjectDictionary<string,TBar>;
....
TRoot = class
value : string
end;
TFoo = class(TRoot)
...
end;
TBar = class(TRoot)
...
end;
因此,最后一部分将从每个集合继承,并创建save/load方法,将每个集合“转换”为/从TDictionary(string,string)
TFooListSavable=TFooList;
程序创建(保存\加载:ISave);
程序保存;
程序负载;
....
结束;
过程TFooListSavable.Save
// 1. 创建一个字典
// 2. 加载上面的字典和我的收藏
//将每个Foo对象转换为字符串
// 3. 调用save\u load.save(字典);
结束;
过程TFooListSavable.Load
// 1. 创建一个字典
// 2. 调用save_load.load加载它
// 3. 移动集合并将字符串转换为TFoo和
// 4. AddOrEquals将创建的每个TFoo添加到TFooListSavable中。
结束;
因此,这种方法有两个问题:
1) 保存或加载的接口需要集合中的字符串值,尽管每个集合中的所有对象都继承自定义了该字符串的类,但我不知道如何将像TDictionary
这样的集合转换为TDictionary
,而无需使用上面的代码(这将复制集合,以便将其传递给iSave
对象)
2) 我觉得,虽然我可以替换
iSave
对象,改变收藏的保存/加载方式,而不改变收藏本身,但我不知道保存/加载收藏的最佳方法是否是保留相关对象。我认为你这样做是错误的
ISave
不应该有任何t词典的概念。它应该只公开用于读取/写入基本数据类型(整数、字符串等)的方法。让t工具可存储
和t工具可存储
根据需要调用ISave
方法,决定如何序列化各自的t词典
数据
如果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;
类型
ISerialize=接口
函数HasData:Boolean;
程序StartWriteCollection;
程序开始编写项目;
过程FinishWriteCollection;
程序完成写入项;
过程writebolean(值:布尔);
过程WriteInteger(值:整数);
过程WriteString(常量值:字符串);
...
收集程序;
程序项目;
收集程序;
程序完成项目;
函数ReadBoolean:Boolean;
函数ReadInteger:Integer;
函数ReadString:String;
...
结束;
特鲁特=阶级
公众的
值:字符串;
构造函数创建;事实上的
过程保存(Dest:iseralize);事实上的
过程加载(Src:iseralize);事实上的
结束;
TBaseList=类(TObjectDictionary)
公众的
过程保存(Dest:iseralize);
过程加载(Src:iseralize);
结束;
TFoo=等级(特罗特)
公众的
myint:整数;
...
过程保存(Dest:iseralize);推翻
过程加载(Src:iseralize);推翻
结束;
TFooList=TBaseList;
TBar=等级(特鲁特)
mybool:布尔型;
...
过程保存(Dest:iseralize);推翻
过程加载(Src:iseralize);推翻
结束;
TBarList=TBaseList;
TDB序列化=类(TInterfacedObject,ISerialize)
...
结束;
TFileSerialize=class(TInterfacedObject,ISerialize)
...
结束;
过程TBaseList.Save(Dest:ISerialize);
变量
配对:TPair;
开始
目的地StartWriteCollection;
为自己做一对
开始
Dest.StartWriteItem;
目的写入限制(对密钥);
特鲁特(双人价值)。保存(目的地);
Dest.FinishWriteItem;
结束;
Dest.FinishWriteCollection;
结束;
过程TBaseList.Load(Src:iseralize);
变量
Cnt,I:整数;
键:字符串;
值:T;
开始
自我清晰;
Src.StartReadCollection;
而Src.HasData
开始
Src.StartReadItem;
key:=Src.ReadString;
值:=T.创建;
尝试
荷载值(Src);
添加(键、值);
除了
价值。自由;
提高;
结束;
Src.finishraditem;
结束;
Src.finishradcollection;
结束;
程序部队保存(目的地:ISerialize);
开始
目的写入限制(值);
结束;
程序组荷载(Src:ISerialize);
开始
值:=Src.ReadString;
结束;
过程TFoo.Save(Dest:iseralize);
开始
继承;
目的写入者(myint);
结束;
过程TFoo.Load(Src:iseralize);
开始
继承;
myint:=Src.ReadInteger;
结束;
程序TBar.Save(目标:ISerialize);
开始
继承;
目的地Writebolean(mybool);
结束;
程序TBar.Load(Src:ISerialize);
开始
继承;
mybool:=Src.ReadBoolean;
结束;
您有一个观点,即每个类(TFoo、TBar)都应该负责将自己转换为字符串。但您不认为集合的加载/保存过程有点“面向流”吗?我认为编写数据库版本(TDbSerialize)很难,不是吗?@MarcosCunhaLima不,我认为这一点都不难。我展示的只是一个例子。如果需要,您可以向ISerialize
添加其他方法,以便DB实现可以为每个集合项创建新记录,然后Write
方法可以根据需要更新记录列,然后在完成时提交。或者为要写入的整个集合创建新blob。你需要什么都行。
TDbSave = class( TInterfacedObject , ISave )
....
end;
iSave := TDbSave( ConnString )
TFileSave = class( TInterfacedObject , ISave )
....
end;
iSave := TFileSave( fileName );
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;
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;