我在 DXE2 上使用 SuperObject(序列化工作正常)反序列化包含来自 json 的接口字段的对象时遇到问题。考虑以下:
ITest = interface(IInterface)
['{9E5623FF-1BC9-4FFA-919D-80C45EE24F38}']
function GetField3() : string;
procedure SetField3(Value: string);
property FField3: string read GetField3 write SetField3;
end;
TTest = class(TInterfacedObject, ITest)
private
FField3: string;
function GetField3() : string;
procedure SetField3(Value: string);
public
property Field3: string read GetField3 write SetField3;
constructor Create(Field3: string);
end;
TMyClass = class(TObject)
public
FField1: string;
FField2: string;
FTest: ITest;
constructor Create(Field1: string; Field2: string; Test: ITest);
end;
// TTest-stuff omitted for brevity.
constructor TMyClass.Create(Field1, Field2: string; Test: ITest);
begin
FField1 := Field1;
FField2 := Field2;
FTest := Test;
end;
var
MyClass: TMyClass;
MyClass2: TMyClass;
JSONObj: ISuperObject;
SuperContext: TSuperRttiContext;
begin
MyClass := TMyClass.Create('Test1', 'Test2', TTest.Create('Test3'));
SuperContext := TSuperRttiContext.Create();
JSONObj := SuperContext.AsJson<TMyClass>(MyClass);
WriteLn(JSONObj.AsString);
MyClass2 := SuperContext.AsType<TMyClass>(JSONObj);
MyClass2.Free();
ReadLn;
end.
当执行到TSuperRttiContext.FromJson.FromClass
检查FTest
-field 时,doo-doo 会撞到天花板上的螺旋桨(或安装在桌面上,如果您愿意的话)。此时,Result := FromJson(f.FieldType.Handle, GetFieldDefault(f, obj.AsObject[GetFieldName(f)]), v);
被调用,这将我们带入 SuperObject.pas 代码中有趣的部分。为简洁起见,我将在这里复制它。
procedure FromInterface;
const soguid: TGuid = '{4B86A9E3-E094-4E5A-954A-69048B7B6327}';
var
o: ISuperObject;
begin
if CompareMem(@(GetTypeData(TypeInfo).Guid), @soguid, SizeOf(TGUID)) then
begin
if obj <> nil then
TValue.Make(@obj, TypeInfo, Value) else
begin
o := TSuperObject.Create(stNull);
TValue.Make(@o, TypeInfo, Value);
end;
Result := True;
end else
Result := False;
end;
分配给的值soguid
是ISuperObject
,所以很明显两者不匹配(我正在测试ITest
,记得吗?)。所以我有点不知道该怎么做。反序列化由一个或多个接口字段组成的任何对象是否违法?
这似乎是一个常见的用例,我很难相信。我可以理解这样一个事实,即知道要选择给定接口的哪种实现可能并非易事。然而,我从序言中的评论中看到,应该支持接口对象 - http://code.google.com/p/superobject/source/browse/trunk/superobject.pas#47。
如果有人在那里解决了这个问题,那当然会很棒。谢谢!:)