Here is my try at this. I have similar task as you (refer to this thread). It's work in progress, but does the job good enough so far. This would enumerate all properties inside the TObject
thou, so you'll have to adapt it to enumerate records:
function EnumerateProperties(const AObject: TObject): String;
var
rt: TRttiType;
prop: TRttiProperty;
value, value2: TValue;
valstr: String;
propstr: String;
fullstr: String;
bres: Boolean;
meth: TRttiMethod;
bytes: TBytes;
bytes_arr: TArray<TBytes>;
uints: TArray<UINT32>;
C1: Integer;
begin
if not Assigned(AObject) then
Exit('');
rt := TRttiContext.Create.GetType(AObject.ClassType);
fullstr := '';
// iterate through public properties
for prop in rt.GetDeclaredProperties do
begin
value := prop.GetValue(AObject); // get property value
valstr := '?';
// check property type
case prop.PropertyType.TypeKind of
tkInteger,
tkInt64,
tkFloat: valstr := value.AsVariant;
tkString,
tkChar,
tkWChar,
tkLString,
tkWString,
tkUString: valstr := QuotedStr(value.AsString);
tkEnumeration: begin
valstr := 'ENUM';
if value.TryAsType<Boolean>(bres) then
valstr := BoolToStr(bres, TRUE)
else
begin
valstr := GetEnumName(value.TypeInfo, prop.GetValue(AObject).AsOrdinal);
end;
end;
tkClass: begin
// check if property is TList or any of its descendants,
// then iterate through each of it's members
meth := prop.PropertyType.GetMethod('ToArray');
if Assigned(meth) then
begin
value2 := meth.Invoke(value, []);
Assert(value2.IsArray);
for C1 := 0 to value2.GetArrayLength - 1 do
valstr := valstr + Format('(%s), ', [EnumerateProperties(value2.GetArrayElement(C1).AsObject)]);
if valstr <> '' then
Delete(valstr, Length(valstr) - 1, 2);
valstr := Format('[%s]', [valstr]);
end
else // otherwise, process it as normal class
valstr := Format('[%s]', [EnumerateProperties(value.AsObject)]);
end;
// dynamic arrays
tkDynArray: begin
if value.TryAsType<TBytes>(bytes) then // TBytes
valstr := BytesToHex(bytes)
else
if value.TryAsType<TArray<TBytes>>(bytes_arr) then // TArray<TBytes>
begin
valstr := '';
for C1 := Low(bytes_arr) to High(bytes_arr) do
valstr := valstr + QuotedStr(BytesToHex(bytes_arr[C1])) + ', ';
if valstr <> '' then
Delete(valstr, Length(valstr) - 1, 2);
valstr := Format('(%s)', [valstr]);
end
else
if value.TryAsType<TArray<UINT32>>(uints) then // TArray<UINT32>
begin
valstr := '';
for C1 := Low(uints) to High(uints) do
valstr := valstr + IntToStr(uints[C1]) + ', ';
if valstr <> '' then
Delete(valstr, Length(valstr) - 1, 2);
valstr := Format('(%s)', [valstr]);
end;
end;
tkUnknown: ;
tkSet: ;
tkMethod: ;
tkVariant: ;
tkArray: ;
tkRecord: ;
tkInterface: ;
tkClassRef: ;
tkPointer: ;
tkProcedure: ;
end;
propstr := Format('%s: %s', [prop.Name, valstr]);
fullstr := fullstr + propstr + '; ';
end;
if fullstr <> '' then
Delete(fullstr, Length(fullstr) - 1, 2);
result := fullstr;
end;