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