Delphi Rtti:如何从TObjectList< T> [英] Delphi Rtti: how to get objects from TObjectList<T>

查看:244
本文介绍了Delphi Rtti:如何从TObjectList< T>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为xml转换器创建一个自定义类,其中一个要求是能够流式传输 TObjectList< T> 字段。

我是试图调用 ToArray()方法来获取TObjectlist的对象,但是我得到'Invalid class typecast',因为类型显然不匹配。



以此类为例:

 类型
TSite = class
名称:String;
地址:String;
end;

TSites = class
网站:TObjecList< TSite>;
end;

我只需要从站点TObjectList中获取站点对象。
请记住,我使用的是RTTI,所以我不知道TObjectList中的ObjectType,因此类型转换不起作用。这是我的,但它似乎是一个死胡同(在这里Obj是 TobjectList< TSite> ):

 函数TXmlPersister.ObjectListToXml(Obj:TObject; Indent:String):String; 

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

begin
结果:='';
TypInfo:= ctx.GetType(Obj.ClassInfo);
Meth:= TypInfo.GetMethod('ToArray');
如果Assigned(Meth)then
begin
Arr:= Invoke(Obj,[])。AsType< TArray< TObject>> //无效的类类型转换错误

if Length(Arr)> 0 then
begin
//从数组中获取对象并对它们进行流式处理
...
end;
end;

任何通过RTTI将对象从TObjectList中取出的方式对我来说都是好的。
出于某种奇怪的原因,我没有在TypInfo中看到GetItem / SetItem方法



编辑



感谢David我有我的解决方案:
$ b $ pre $ 函数TXmlPersister.ObjectListToXml(Obj:TObject; Indent :String):String;

var
TypInfo:TRttiType;
meth:TRttiMethod;
值:TValue;
计数:整数;

begin
结果:='';
TypInfo:= ctx.GetType(Obj.ClassInfo);
Meth:= TypInfo.GetMethod('ToArray');
如果Assigned(Meth)那么
begin
Value:= Meth.Invoke(Obj,[]);
Assert(Value.IsArray);
Count:= Value.GetArrayLength;
,而计数> 0 do
begin
Dec(Count);
结果:= Result + ObjectToXml(Value.GetArrayElement(Count).AsObject,Indent);
end;
end;
end;

我很乐意提供建议,也许还有更多'聪明'的方法来实现这个目标......

解决方案

您的代码因为动态数组不是TObject而失败。



<你可以这样做:

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


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...

解决方案

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;

这篇关于Delphi Rtti:如何从TObjectList&lt; T&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆