2012-09-19 58 views
3

我工作的自定義類,以XML轉換和要求之一是流TObjectList<T>領域的能力得到對象。
我試圖調用ToArray()方法來獲取TObjectlist的對象保持,但我得到「無效的類類型轉換」,因爲該類型的明顯不匹配。德爾福RTTI:如何從TObjectList <T>

藉此類,例如:

type 
    TSite = class 
    Name : String; 
    Address : String; 
    end; 

    TSites = class 
    Sites : TObjecList<TSite>; 
    end; 

我只需要得到網站從網站TObjectList對象。 請記住,我使用RTTI,所以我不知道對象類型中TObjectList,所以鑄字都不行。這是我有,但它似乎是一個死衚衕(obj是TobjectList<TSite>這裏):

function TXmlPersister.ObjectListToXml(Obj : TObject; Indent: String): String; 

var 
    TypInfo: TRttiType; 
    meth: TRttiMethod; 
    Arr : TArray<TObject>; 

begin 
Result := ''; 
TypInfo := ctx.GetType(Obj.ClassInfo); 
Meth := TypInfo.GetMethod('ToArray'); 
if Assigned(Meth) then 
    begin 
    Arr := Invoke(Obj, []).AsType<TArray<TObject>>; // invalid class typecast error 

    if Length(Arr) > 0 then 
    begin 
    // get objects from array and stream them 
    ... 
    end; 
    end; 

任何方式來獲得的物品運通過RTTI的TObjectList的是爲我好。 對於一些奇怪的原因,我沒有看到TypInfo爲getItem/SetItem方法

編輯

感謝David我有我的解決方案:

function TXmlPersister.ObjectListToXml(Obj : TObject; Indent: String): String; 

var 
    TypInfo: TRttiType; 
    meth: TRttiMethod; 
    Value: TValue; 
    Count : Integer; 

begin 
Result := ''; 
TypInfo := ctx.GetType(Obj.ClassInfo); 
Meth := TypInfo.GetMethod('ToArray'); 
if Assigned(Meth) then 
    begin 
    Value := Meth.Invoke(Obj, []); 
    Assert(Value.IsArray); 
    Count := Value.GetArrayLength; 
    while Count > 0 do 
    begin 
    Dec(Count); 
    Result := Result + ObjectToXml(Value.GetArrayElement(Count).AsObject, Indent); 
    end; 
    end; 
end; 

我開放的建議,也許還有更「聰明」的方式來實現這一目標?

+0

爲什麼你需要把項目中的數組?你能否不只是調用'GetItem'而是逐一讀取每個項目?您可以將結果存儲在「TObject」中,而不必知道「T」。 –

+0

@RobKennedy,由於某些原因,我在迭代typeinfo.GetMethods()時找不到方法。 – whosrdaddy

回答

4

你的代碼,因爲動態數組是不是一個TObject的失敗。

你可以這樣說:

Value := Meth.Invoke(Obj, []); 
Assert(Value.IsArray); 
SetLength(Arr, Value.GetArrayLength); 
for i := 0 to Length(Arr)-1 do 
    Arr[i] := Value.GetArrayElement(i).AsObject;