Class with builtin marshalling. Why are the field converters not working?
I have the following questions:
- Should the marshalling be placed in a class helper instead? Or is it quite OK to place it "inside" the class?
- Why are the field converters not working?
Using Delphi XE - consider this:
type
TMyClass = Class
public
FaString : String;
FaStringList : TStringList;
FMar : TJsonMarshal;
procedure RegisterConverters;
function Marshal : TJsonObject; // should handle marshalling
end;
RegisterConverters would look something like this.
procedure TMyClass.RegisterConverters;
begin
// try and catch the marshaller itself.
FMar.RegisterConverter(TJsonMarshal, 'FMar',
function(Data : TObject; Field:String): TObject
begin
Exit(nil); // Since we cannot marshal it - and we dont need it anyways.
end);
// catch TStringList
FMar.RegisterConverter(TStringList, 'FaStringList'开发者_C百科,
function(Data: TObject; Field:String): TListOfStrings
var
i, count: integer;
begin
count := TStringList(Data).count;
SetLength(Result, count);
for i := 0 to count - 1 do
Result[i] := TStringList(Data)[i];
end);
end;
And the Marshal method :
function TMyClass.Marshal: TJSONObject;
begin
if FMar = nil then
FMar := TJSONMarshal.Create(TJSONConverter.Create);
try
RegisterConverters;
try
Result := FMar.Marshal(Self) as TJSONObject;
except
Result := nil;
end;
finally
FMar.Free;
end;
end;
Then we can do this:
var
aObj : TMyClass;
ResultString : String;
begin
aObj := TMyClass.Create;
aObj.FaString := 'Test string';
aObj.FaStringList := TStringList.Create;
aObj.FaStringList.Add('stringliststring #1');
aObj.FaStringList.Add('stringliststring #2');
aObj.FaStringList.Add('stringliststring #3');
aObj.FaStringList.Add('stringliststring #4');
// StringList and JsonMarshal should be handled by converter
ResultString := (aObj.Marshal).ToString;
end;
But I simply cannot get it working. Field Converters do not get triggered?
Am I doing something wrong here? Or should I look at my Delphi XE installation (perhaps it is pooched)?
When doing the marshal from "within" you have to set it up correctly :-)
procedure TMyClass.RegisterConverters;
begin
// try and catch the marshaller itself.
FMar.RegisterConverter(ClassType, 'FMar',
function(Data : TObject; Field:String): TObject
begin
Exit(nil); // Since we cannot marshal it - and we dont need it anyways.
end);
// catch TStringList
FMar.RegisterConverter(ClassType, 'FaStringList',
function(Data: TObject; Field:String): TListOfStrings
var
i, count: integer;
begin
count := TStringList(Data).count;
SetLength(Result, count);
for i := 0 to count - 1 do
Result[i] := TStringList(Data)[i];
end);
end;
The difference is using ClassType as the type in the call to RegisterConverter. Otherwise one cannot get to the specified field - I should have seen that !
精彩评论