I've made so test trying to serialize objects list. Here are a few remarks that I hope will help other users :
Serializing objects list :
- Ngs (NgSerializor) needs to use converters
- for each object list class we need to have an attribut indicating the converter to use
- Different object list class can use the same converter if they deal with objects descendants of the base list using the convertor
- object list cannot be deserialize directly, they must be owned by an object
ex : MyObjectList:=vDeserializer.Value<TMyObjectListType> //will not work, in read method of the converter the parameter "V" will be nil
Here is the source of a little test project with comments :
Ps : I tried to attach the file but the browser told me I didn't accept these file type (*.pas or * .Zip)
unit wMainFrm;
{
Serializing objects list
- Ngs (NgSerializor) needs to use converters
- for each object list class we need to have an attribut indicating the converter to use
- Different object list class can use the same converter if they deal with objects descendants of the base list using the convertor
- object list cannot be deserialize directly, they must be owned by an object
ex : MyObjectList:=vDeserializer.Value<TMyObjectListType> will not work, in read method of the converter the parameter "V" will be nil
}
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Buttons,
system.Generics.Defaults,
system.Generics.collections,
NG.Serialization,
NG.Serialization.Binary, Vcl.StdCtrls;
type
TMyObjectType = class(Tobject)
end;
TwdeMySecondObjectType=Class(TMyObjectType)
protected
fvalue1 : Longint;
fName : String;
fValue2 : String;
fValue3 : Word;
public
property value1 : Longint read fvalue1 write fvalue1;
property Name : String read fName write fName;
property Value2 : String read fValue2 write fValue2;
property Value3 : Word read fValue3 write fValue3;
End;
TwdeObjectsListConverter=Class(TConverter)
public
function GetReadMode: TReadMode; override;
procedure Write(S: TSerializer; const V); override;
procedure Read(D: TDeserializer; var V); override;
end;
[Converter(TwdeObjectsListConverter)]
TMyCustomObjectsList<T:TMyObjectType>=Class(TObjectList<T>)
End;
TMyObjectsList=TMyCustomObjectsList<TMyObjectType>;
[Converter(TwdeObjectsListConverter)]
TmyDescendantObjectsList = Class(TMyCustomObjectsList<TwdeMySecondObjectType>);
TwdeDictionnary = Class(Tobject)
fMyItemsList : TmyDescendantObjectsList;
public
constructor create;
destructor Destroy;override;
End;
TForm1 = class(TForm)
Button_Test: TSpeedButton;
Memo1: TMemo;
procedure Button_TestClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$Region 'TwdeObjectsListConverter'}
{------------------------------------------------------------------------------}
function TwdeObjectsListConverter.GetReadMode: TReadMode;
begin
result:=rmNormal;
end;
{------------------------------------------------------------------------------}
procedure TwdeObjectsListConverter.Read(D: TDeserializer; var V);
var
vList : TMyObjectsList;
vObject: TMyObjectType;
begin
D.BeginArray;
vList:=TMyObjectsList(v);
vList.Clear;
while D.HasNext do
begin
vObject:=D.Value<TMyObjectType>;
vList.Add(vObject);
end;
D.EndArray;
end;
{------------------------------------------------------------------------------}
procedure TwdeObjectsListConverter.Write(S: TSerializer; const V);
var
va: Integer;
vDicoRec: TwdeMySecondObjectType;
vList: TMyObjectsList;
vObject: TMyObjectType;
begin
S.BeginArray('Items');
vList := TMyObjectsList(v);
for va := 0 to vList.Count - 1 do
begin
vObject:=vList[va];
vDicoRec:=TwdeMySecondObjectType(vObject);
S.Value(vObject);
end;
S.EndArray;
end;
{------------------------------------------------------------------------------}
{$EndRegion 'TwdeObjectsListConverter'}
{$R *.dfm}
{------------------------------------------------------------------------------}
procedure TForm1.Button_TestClick(Sender: TObject);
var
vDicoRecord: TwdeMySecondObjectType;
vStream : TmemoryStream;
vSerializator : TBinarySerializer;
vDeserializer : TBinaryDeserializer;
vDictionnary : TwdeDictionnary;
va : Longint;
begin
vDictionnary:=TwdeDictionnary.Create;
for va:=1 to 100000 do
begin
vDicoRecord:=TwdeMySecondObjectType.Create;
vDicoRecord.Name:='Value_'+IntTostr(va);
vDicoRecord.fValue2:='Value_'+IntTostr(va);
vDictionnary.fMyItemsList.Add(vDicoRecord)
end;
vStream:=TMemoryStream.Create;
vSerializator:=TBinarySerializer.Create(vStream);
vSerializator.Value(vDictionnary);
vSerializator.FlushBuffer;
vSerializator.Free;
vStream.Position:=0;
vDeserializer:=TBinaryDeserializer.Create(vStream);
vDictionnary:=vDeserializer.Value<TwdeDictionnary>;
Memo1.Lines.Add('count : '+IntToStr(vDictionnary.fMyItemsList.Count));
end;
{------------------------------------------------------------------------------}
{$Region 'TwdeDictionnary'}
{------------------------------------------------------------------------------}
constructor TwdeDictionnary.create;
begin
fMyItemsList:=TmyDescendantObjectsList.Create(true);
end;
{------------------------------------------------------------------------------}
destructor TwdeDictionnary.Destroy;
begin
fMyItemsList.Free;
inherited;
end;
{------------------------------------------------------------------------------}
{$Region 'TwdeDictionnary'}
end.
Comments