Delphi Rtti: как получить объекты из TObjectList<T>
Я работаю с пользовательским классом в XML-конвертер, и одним из требований является возможность потоковой передачи TObjectList<T>
поля.
Я пытаюсь вызвать ToArray()
метод, чтобы получить объекты TObjectlist, но я получаю 'Недопустимый тип Typecast', потому что типы, очевидно, не совпадают.
возьмем этот класс, например:
type
TSite = class
Name : String;
Address : String;
end;
TSites = class
Sites : TObjecList<TSite>;
end;
Мне просто нужно получить объекты сайта из списка сайтов TObjectList. Помните, что я использую RTTI, поэтому я не знаю ObjectType в TObjectList, поэтому Typecasting не будет работать. Это то, что у меня есть, но, похоже, тупик 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;
Любой способ получить объекты из TObjectList через RTTI мне подходит. По какой-то странной причине я не вижу методы GetItem/SetItem в TypInfo
РЕДАКТИРОВАТЬ
Благодаря Дэвиду у меня есть решение:
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;
Я открыт для предложений, может быть, есть более "умные" способы для достижения этой цели...
1 ответ
Ваш код не выполняется, потому что динамический массив не является объектом 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;