2013-06-20 28 views
2

我試圖用TJSONMarshal(XE4)序列化對象,但是當對象具有像_recordset這樣的接口屬性時,我遇到了一個問題我可以用TJSONMarshal序列化一個接口(_recordset)嗎?

例如,

我的類:

TFoo = class 
    private 
    FrsFoo: _recordset; 
    FFooProp: integer; 
    published 
    property rsFoo: _recordset read FrsFoo write FrsFoo; 
    property FooProp: integer read FFooProp write FFooProp; 
    end; 

我的功能:

function TestSerialize: string; 
var 
    JsonMarshal: TJSONMarshal; 
    Foo: TFoo; 
begin 
    JsonMarshal := TJSONMarshal.Create(TJSONConverter.Create); 
    Foo := TFoo.Create; 
    Result := JsonMarshal.Marshal(Foo).ToString; 
end; 

它的結果:

{ 「類型」: 「uTest.TFoo」, 「ID」:1, 「fields」:{「FFooProp」:0}}

rsFoo未序列化!

我可以序列化它嗎?或者是它對TJSONMarshal的限制?

+1

因爲沒有實現,所以接口不能很容易地序列化,它們只是接口。您如何期望序列化工作?您可能需要獲得實現來支持提供序列化服務的另一個接口。 –

+0

是的你是對的!但我有一個使用rtti將serialize對象轉換爲XML的實現,當出現「_recordset」時,我將它保存到一個流(TStringStream)中,這就是我如何獲得它的「序列化」。我想也許我可以用TJSONMarshal做那樣的事情,但「TJSONMarshal.RegisterConverter」只接受TClass –

回答

1

在我來說,我只是想序列_recordsets所以我的解決辦法是:

1)獲取所有_Recordset類型字段:

function Test.GetRecordsetFieldsFromObject(
    AObject: TObject): TStringList; 
var 
    Obj: TRttiType; 
    Rtti: TRTTIContext; 
    ObjField: TRttiField; 
    IntfObj: IInterface; 
    rsOut: _recordset; 
begin 
    Result := TStringList.Create; 
    Obj := Rtti.GetType(AObject.ClassType); 
    for ObjField in Obj.GetFields do 
    if ObjField.FieldType.TypeKind = tkInterface then 
    begin 
     IntfObj := ObjField.GetValue(AObject).AsInterface; 
     if IntfObj.QueryInterface(_Recordset, rsOut) = 0 then 
     begin 
     Result.Add(ObjField.Name); 
     rsOut := nil; 
     end; 
    end; 
end; 

2)註冊轉換器和返還的每個字段創建

for FieldName in FieldNameList do 
    begin 
    JsonMarshal.RegisterConverter(TFoo, FieldName, function(Data: TObject; Field: String): TListOfStrings 
    var 
     Obj: TRttiType; 
     ObjField: TRttiField; 
     rsProp: _Recordset; 
     strStream: TStringStream; 
    begin 
     SetLength(Result, 1); 
     strStream := TStringStream.Create; 
     try 
     Obj := Rtti.GetType(data.ClassType); 
     ObjField := Obj.GetField(Field); 
     rsProp := ObjField.GetValue(Data).AsInterface as _Recordset; 
     rsProp.Save(TStreamAdapter.Create(strStream) as IUnknown, adPersistXML); 
     Result[0] := strStream.DataString; 
     finally 
     rsProp := nil; 
     strStream.Free; 
     end; 
    end); 

    JsonUnMarshal.RegisterReverter(TFoo, FieldName, procedure(Data: TObject; Field: String; Args: TListOfStrings) 
    var 
     Obj: TRttiType; 
     ObjField: TRttiField; 
     rsProp: _Recordset; 
     strStream: TStringStream; 
    begin 
     rsProp := coRecordset.Create; 
     strStream := TStringStream.Create(Args[0]); 
     try 
     Obj := Rtti.GetType(data.ClassType); 
     ObjField := Obj.GetField(Field); 
     strStream.Position := 0; 
     rsProp.Open(TStreamAdapter.Create(strStream) as IUnknown, EmptyParam, adOpenUnspecified, adLockUnspecified, 0); 
     ObjField.SetValue(Data, TValue.From<_Recordset>(rsProp)); 
     finally 
     rsProp := nil; 
     strStream.Free; 
     end; 
    end); 
    end; 
相關問題