最好提到这一点:
我正在使用 Delphi XE2 - 但 XE 或 2010 也应该可以解决问题:-)
这个问题现在在质量中心 QC#99313 请投票:-)
截至 2011 年 10 月 20 日,Embarcadero 已将 QC 报告标记为已解决。
解决方案由 SilverKnight 提供。但 Embarcadero 缺乏信息让我感到担忧。由于该解决方案建议使用 XE(2) 帮助系统、其他论坛和 CC 中解释的源代码以外的其他源代码。但是你自己看看QC。
鉴于这些类型声明:
type
TTestObject : Class
aList : TStringList;
function Marshal : TJSonObject;
end;
TTestObjectList<T:TestObject> : Class(TObjectList<T>)
function Marshal : TJSonObject; // How to write this ?
end;
我想为 TTestObjectList 实现 Marshal 方法。
据我所知 - 我应该为 TTestObject 和美丽注册一个转换器
其中 - 为每个元素调用 Marshal。
TTestObject 的 Marshal 注册了这个转换器:
RegisterConverter(TStringList,
function(Data: TObject): 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);
通用 TTestObjectList 编码(marshal)方法:
function TTestObjectList<T>.Marshal: TJSONObject;
var
Mar : TJsonMarshal; // is actually a property on the list.
begin
Mar := TJsonMarshal.Create(TJSONConverter.Create);
try
RegisterConverter(TTestObject,
function(Data: TObject): TObject
begin
Result := TTestObject(Data).Marshal;
end);
Result := Mar.Marshal(Self) as TJSONObject;
finally
Mar.Free;
end;
end;
这是使用列表的简化示例。
var
aTestobj : TTestObject;
aList : TTestObjectList<TTestObject>;
aJsonObject : TJsonObject;
begin
aTestObj := TTestObject.Create; // constructor creates and fills TStringlist with dummy data.
aJsonObject := aTestObj.Marshal; // This works as intended.
aList := TTestObjectList<TTestObject>.Create;
aJsonObject := aList.Marshal; // Fails with tkpointer is unknown ....
end;
当然,我有类似的恢复功能(解码)。
但是上面的代码应该可以工作 - 至少据我所知。
因此,如果有人可以向我指出:
为什么列表无法编码?
我知道我的列表中有 TJsonMarshal 属性 - 但它也有一个转换器/还原器。
更改为 TTypeStringConverter(而不是 TTypeObjectConverter)将返回有效字符串。但我喜欢一直在 TJsonObject 上工作的想法。否则,在从字符串解码到 TTestObject 时,我会遇到同样的问题(或类似的问题)。
任何建议/想法都是最受欢迎的。
最佳答案
我不确定您为什么会收到该错误。在 Delphi XE 中,以下内容似乎对我有用:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes, Contnrs,
Generics.Defaults, Generics.Collections,
DbxJson, DbxJsonReflect;
type
TTestObject = class(TObject)
aList : TStringList;
function Marshal : TJSonObject;
public
constructor Create;
destructor Destroy; override;
end;
TTestObjectList<T:TTestObject,constructor> = class(TObjectList<T>)
function Marshal: TJSonObject;
constructor Create;
end;
{ TTestObject }
constructor TTestObject.Create;
begin
inherited Create;
aList := TStringList.Create;
aList.Add('one');
aList.Add('two');
aList.Add('three');
end;
destructor TTestObject.Destroy;
begin
aList.Free;
inherited;
end;
function TTestObject.Marshal: TJSonObject;
var
Marshal: TJSONMarshal;
begin
Marshal := TJSONMarshal.Create(TJSONConverter.Create);
try
Marshal.RegisterConverter(TStringList,
function (Data: TObject): 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
);
Result := Marshal.Marshal(Self) as TJSONObject;
finally
Marshal.Free;
end;
end;
{ TTestObjectList<T> }
constructor TTestObjectList<T>.Create;
begin
inherited Create;
Add(T.Create);
Add(T.Create);
end;
function TTestObjectList<T>.Marshal: TJSonObject;
var
Marshal: TJsonMarshal;
begin
Marshal := TJSONMarshal.Create(TJSONConverter.Create);
try
Marshal.RegisterConverter(TTestObject,
function (Data: TObject): TObject
begin
Result := T(Data).Marshal;
end
);
Result := Marshal.Marshal(Self) as TJSONObject;
finally
Marshal.Free;
end;
end;
procedure Main;
var
aTestobj : TTestObject;
aList : TTestObjectList<TTestObject>;
aJsonObject : TJsonObject;
begin
aTestObj := TTestObject.Create;
aJsonObject := aTestObj.Marshal;
Writeln(aJsonObject.ToString);
Writeln;
aList := TTestObjectList<TTestObject>.Create;
aJsonObject := aList.Marshal;
Writeln(aJsonObject.ToString);
Readln;
end;
begin
try
Main;
except
on E: Exception do
begin
ExitCode := 1;
Writeln(Format('[%s] %s', [E.ClassName, E.Message]));
end;
end;
end.
关于delphi - 泛型和编码(marshal)/UnMarshal。我在这里缺少什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7528829/