最好提到这一点:
我正在使用 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/

10-09 04:16