我正在开发一个自定义的类到XML转换器,其中一个要求是能够流式传输TObjectList<T>
字段。
我试图调用ToArray()
方法来获取TObjectlist的对象,但由于类型显然不匹配,所以我得到了“无效的类类型转换”错误。
以这个类为例:
type
TSite = class
Name : String;
Address : String;
end;
TSites = class
Sites : TObjecList<TSite>;
end;
我只需要从Sites TObjectList 中获取Site Objects。 请记住我正在使用RTTI,所以我不知道TObjectList中的ObjectType,因此强制类型转换是行不通的。这是我目前的代码,但似乎走到了死胡同(Obj在这里是TobjectList ):
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;
我可以给出建议,也许有更加“聪明”的方法来实现这个目标...
GetItem
逐个读取每个项目吗?您可以将结果存储在TObject
中,而无需了解T
。 - Rob Kennedy