Generics and Marshal / UnMarshal. What am I missing here?
在“第1部分”(上面的链接)中,TOndrej提供了一个很好的解决方案 – 在XE2上失败了.
在这里,我提供纠正的来源来纠正这一点
而且我认为有必要进一步扩展这个问题.
所以我想听听大家如何做到这一点:
首先 – 要在XE2和XE2更新1上运行源,请进行以下更改:
Marshal.RegisterConverter(TTestObject,function (Data: TObject): String // <-- String here begin Result := T(Data).Marshal.ToString; // <-- ToString here end );
为什么?
我能看到的唯一原因必须与XE2有关,因为它有更多可用的RTTI信息.因此它将尝试并封送返回的TObject.
我在这里走在正确的轨道上吗?请随意发表评论.
更重要的是 – 该示例未实现UnMarshal方法.
如果有人可以制作一个并在此发布我会喜欢它:-)
我希望你仍然对这个问题感兴趣.
亲切的问候
比亚
出于某种原因,使用TJsonobject的非默认构造函数导致XE2中的问题 – 使用默认构造函数“修复”问题.
首先,您需要将TTestobject移动到自己的单元 – 否则,在尝试解组时,RTTI将无法找到/创建您的对象.
unit uTestObject; interface uses SysUtils,Classes,Contnrs,Generics.Defaults,Generics.Collections,DbxJson,DbxJsonReflect; type {$RTTI EXPliCIT METHODS([]) PROPERTIES([vcpublished]) FIELDS([vcPrivate])} TTestObject=class(TObject) private aList:TStringList; public constructor Create; overload; constructor Create(List: array of string); overload; constructor Create(List:TStringList); overload; destructor Destroy; overrIDe; function Marshal:TJsonObject; class function Unmarshal(value: TJsONObject): TTestObject; published property List: TStringList read aList write aList; end; implementation { TTestObject } constructor TTestObject.Create; begin inherited Create; aList:=TStringList.Create; end; constructor TTestObject.Create(List: array of string); var I:Integer; begin Create; for I:=low(List) to high(List) do begin aList.Add(List[I]); end; end; constructor TTestObject.Create(List:TStringList); begin Create; aList.Assign(List); end; destructor TTestObject.Destroy; begin aList.Free; inherited; end; function TTestObject.Marshal:TJsonObject; var Mar:TJsONMarshal; begin Mar:=TJsONMarshal.Create(); try Mar.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:=Mar.Marshal(Self) as TJsonObject; finally Mar.Free; end; end; class function TTestObject.Unmarshal(value: TJsONObject): TTestObject; var Mar: TJsONUnMarshal; L: TStringList; begin Mar := TJsONUnMarshal.Create(); try Mar.RegisterReverter(TStringList,function(Data: TlistofStrings): TObject var I,Count: Integer; begin Count := Length(Data); Result:=TStringList.Create; for I := 0 to Count - 1 do TStringList(Result).Add(string(Data[I])); end ); //UnMarshal will attempt to create a TTestObject from the TJsONObject data //using RTTI lookup - for that to function,the type MUST be defined in a unit Result:=Mar.UnMarshal(Value) as TTestObject; finally Mar.Free; end; end; end.
另请注意,构造函数已经过载 – 这使您可以在创建过程中看到代码是有用的,而无需预先设置对象中的数据.
这是泛型类列表对象的实现
unit uTestObjectList; interface uses SysUtils,DbxJsonReflect,uTestObject; type {$RTTI EXPliCIT METHODS([]) PROPERTIES([]) FIELDS([])} TTestObjectList<T:TTestObject,constructor> = class(TObjectList<T>) public function Marshal: TJsonObject; constructor Create; class function Unmarshal(value: TJsONObject): TTestObjectList<T>; static; end; //Note: this MUST be present and initialized/finalized so that //delphi will keep the RTTI information for the generic class available //also,it MUST be "project global" - not "module global" var X:TTestObjectList<TTestObject>; implementation { TTestObjectList<T> } constructor TTestObjectList<T>.Create; begin inherited Create; //removed the add for test data - it corrupts unmarshaling because the data is already present at creation end; function TTestObjectList<T>.Marshal: TJsonObject; var Marshal: TJsonMarshal; begin Marshal := TJsONMarshal.Create; try Marshal.RegisterConverter(TTestObjectList<T>,function(Data: TObject): TlistofObjects var I: integer; begin SetLength(Result,TTestObjectList<T>(Data).Count); for I:=0 to TTestObjectList<T>(Data).Count-1 do Result[I]:=TTestObjectList<T>(Data)[I]; end ); Result := Marshal.Marshal(Self) as TJsONObject; finally Marshal.Free; end; end; class function TTestObjectList<T>.Unmarshal(value: TJsONObject): TTestObjectList<T>; var Mar: TJsONUnMarshal; L: TStringList; begin Mar := TJsONUnMarshal.Create(); try Mar.RegisterReverter(TTestObjectList<T>,function(Data: TlistofObjects): TObject var I,Count: Integer; begin Count := Length(Data); Result:=TTestObjectList<T>.Create; for I := 0 to Count - 1 do TTestObjectList<T>(Result).Unmarshal(TJsONObject(Data[I])); end ); //UnMarshal will attempt to create a TTestObjectList<TTestObject> from the TJsONObject data //using RTTI lookup - for that to function,the type MUST be defined in a unit,//and,because it is generic,there must be a GLOBAL VARIABLE instantiated //so that Delphi keeps the RTTI information avaialble Result:=Mar.UnMarshal(Value) as TTestObjectList<T>; finally Mar.Free; end; end; initialization //force delphi RTTI into maintaining the Generic class information in memory x:=TTestObjectList<TTestObject>.Create; finalization X.Free; end.
有几件事需要注意:
如果在运行时创建泛型类,则不保留RTTI信息,除非在内存中存在对该类的全局可访问对象引用.见:Delphi: RTTI and TObjectList<TObject>
因此,上面的单元创建了这样一个变量,并将其实例化,如链接文章中所讨论的那样.
主要过程已更新,显示两个对象的数据编组和解组:
procedure Main; var aTestobj,bTestObj,cTestObj : TTestObject; aList,bList : TTestObjectList<TTestObject>; aJsonObject,bJsonObject,cJsonObject : TJsonObject; s: string; begin aTestObj := TTestObject.Create(['one','two','three','four']); aJsonObject := aTestObj.Marshal; s:=aJsonObject.ToString; Writeln(s); bJsonObject:=TJsonObject.Create; bJsonObject.Parse(BytesOf(s),length(s)); bTestObj:=TTestObject.Unmarshal(bJsonObject) as TTestObject; writeln(bTestObj.List.Text); writeln('TTestObject marshaling complete.'); readln; aList := TTestObjectList<TTestObject>.Create; aList.Add(TTestObject.Create(['one','two'])); aList.Add(TTestObject.Create(['three'])); aJsonObject := aList.Marshal; s:=aJsonObject.ToString; Writeln(s); cJsonObject:=TJsonObject.Create; cJsonObject.Parse(BytesOf(s),length(s)); bList:=TTestObjectList<TTestObject>.Unmarshal(cJsonObject) as TTestObjectList<TTestObject>; for cTestObj in bList do begin writeln(cTestObj.List.Text); end; writeln('TTestObjectList<TTestObject> marshaling complete.'); Readln; end;总结
以上是内存溢出为你收集整理的德尔福 – 泛型和元帅/ UnMarshal.我在这里错过了什么?第2部分 :-)全部内容,希望文章能够帮你解决德尔福 – 泛型和元帅/ UnMarshal.我在这里错过了什么?第2部分 :-)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)