【发布时间】:2012-12-19 17:00:14
【问题描述】:
我想知道如何执行通用TObjectList<T> 容器的序列化。基本上,我想在该列表中存储不同的对象,但所有对象都将来自TSerializable,其定义如下:
TSerializable = class abstract(TObject)
public
{ Public declarations }
procedure LoadFromStream(const S: TStream); virtual; abstract;
procedure SaveToStream(const S: TStream); virtual; abstract;
end;
现在,假设我在应用程序的某处定义了这些类:
type
TExampleClass = class(TSerializable)
private
{ Private declarations }
FIntProp: Integer;
public
{ Public declarations }
constructor Create();
procedure LoadFromStream(const S: TStream); override;
procedure SaveToStream(const S: TStream); override;
property IntProp: Integer read FIntProp write FIntProp;
end;
TAnotherExample = class(TSerializable)
private
{ Private declarations }
FStringProp: String;
public
{ Public declarations }
constructor Create();
procedure LoadFromStream(const S: TStream); override;
procedure SaveToStream(const S: TStream); override;
procedure ReverseStringProp();
property StringProp: String read FStringProp write FStringProp;
end;
我打算将这些对象存储在一个列表中:
var
MS: TMemoryStream;
SomeList: TObjectList<TSerializable>;
begin
MS := TMemoryStream.Create();
SomeList := TObjectList<TSerializable>.Create(True);
try
SomeList.Add(TExampleClass.Create());
SomeList.Add(TAnotherClass.Create());
TExampleClass(SomeList[0]).IntProp := 1992;
TAnotherClass(SomeList[1]).StringProp := 'Some value';
// Here, a method to serialize the list...
SerializeList(SomeList, MS);
// Clear the list and reset position in the stream.
SomeList.Clear();
MS.Seek(0, soFromBeginning);
// Unserialize the list.
UnserializeList(SomeList, MS);
// Should display "Some value".
Writeln(TAnotherClass(SomeList[1]).StringProp);
finally
SomeList.Free();
MS.Free();
end;
end;
现在,我怎么可能将整个列表序列化为流,然后从该流中重新创建列表?
我当时想的是:
- 遍历列表。
- 先将每个对象的类名写入流。
- 对该对象调用
SaveToStream()。
但要让这种方法发挥作用,我需要创建某种类寄存器,它是某种用于存储已知类的字典。这听起来是个好主意,但是我需要调用一些 RegisterClass() 方法来将每个新类添加到字典中,我不太喜欢这种方式。
还有其他方法吗,或者我应该按照我建议的方式去做吗?
非常感谢。
【问题讨论】:
-
当然可以。你必须(再次)解决之前已经解决了很多次的所有问题。
-
我没有更多建议了。使用 JSON 或 XML。并使用众多序列化库之一。不要重新发明轮子。通常,当您这样做时,您的车轮会出现拐角。
-
我和@DavidHeffernan 在同一页上,如果你想要一些已经制作好的东西,omnixml 是一个很好的选择,现在使用它很多年了code.google.com/p/omnixml
-
您可以使用扩展 RTTI 序列化任何对象。无需从 TSerializable 类继承..
-
@whosrdaddy 可能会导致更快的加载/保存或以正确的顺序排序属性。有些人认为 RTTI 是在重新发明轮子。
标签: delphi generics serialization