Search code examples
delphidelphi-xe2datasnap

Delphi XE2 Datasnap TObject with TMemoryStream


How to transfer TObject with TMemoryStream through datasnap?

TMyObject = class(TBizObject)
  FText: TMemoryStream;  <-- Content not sent
  ...
end

on server side

TServerMethods.GetMyClass(const AId: Integer): TMyObject
begin
  Result := TMyObject.find(AId);
end;

On client side TMyObject in correctly unmarshalled except that FText content is empty.

TMemoryStream Json content

"FText": {
        "type":"System.Classes.TMemoryStream",
        "id":2,
        "fields":{
            "FCapacity":16384,
            "FSize":11788,
            "FPosition":11788
        }
    }

Solution

  • The key was to create TConverterEvent and TReverterEvent with field type *. It was hard to find solution without having a source code.

    procedure RegisterDatasnapConvertersAndReverters;
    var
      LConverter: TConverterEvent;
      LReverter: TReverterEvent;
    begin
      LConverter := TConverterEvent.Create(TMemoryStream, '*' {FIELD_ANY});
      LConverter.TypeStringConverter := function (Data: TObject): string
        var
          stream: TMemoryStream;
        begin
          stream := TMemoryStream(Data);
          stream.Position := 0;
          Result := EncodeBase64(stream.Memory, stream.Size);
        end;
      TJSONConverters.AddConverter(LConverter);
    
      LReverter := TReverterEvent.Create(TMemoryStream, '*' {FIELD_ANY});
      LReverter.TypeStringReverter := function(Data: string): TObject
        var
          bytes: TBytes;
        begin
          bytes := DecodeBase64(Data);
          Result := TMemoryStream.Create;
          if nil <> bytes then
            TMemoryStream(Result).WriteBuffer(bytes[0], Length(bytes));
        end;
      TJSONConverters.AddReverter(LReverter);
    end;
    
    initialization
      RegisterDatasnapConvertersAndReverters;