Delphi Rtti: how to get objects from TObjectList<T>

谁都会走 提交于 2019-12-05 04:34:55

问题


I am working a custom class to xml converter and one of the requirements is the ability to stream TObjectList<T> fields.
I am trying to invoke the ToArray() method to get hold of the TObjectlist's objects, but I get 'Invalid class typecast' because the types obviously don't match.

take this class for example:

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

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

I just need to get the Site Objects from the Sites TObjectList. Please keep in mind that I am using RTTI, so I don't know the ObjectType in TObjectList, so Typecasting won't work. This is what I have but it seems a dead end (Obj is TobjectList<TSite> here):

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;

Any way to get the objects out of the TObjectList via RTTI is good for me. For some odd reason I don't see the GetItem/SetItem methods in TypInfo

EDIT

Thanks to David I have my solution:

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;

I am open for suggestions, maybe there are more 'clever' ways to achieve this goal...


回答1:


Your code fails because a dynamic array is not a TObject.

You can do it like this:

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;


来源:https://stackoverflow.com/questions/12497843/delphi-rtti-how-to-get-objects-from-tobjectlistt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!