2

I coded a RttiHelper class, that among other things, can retrieve all field's names of a class. The procedure succesfully determines if a field is an object or an array, but it cannot determine if a field is a Record. Follows code:

unit Form1
interface
uses RttiHelper;
type
  tMyRec = Record
   ...
  end;      
...
implementation
var MyRec : tMyRec;
procedure FormCreate (Sender: tObject);
begin
  SetRec (@MyRec);
end;

unit RttiHelper
interface
type
  tObjRec =  class
   Rec    : Pointer;
  end; 
  ...
  tRttiHelperClass = class (tObject)
  private  
    fObjRec: tObjRec;
  ...
    procedure GetFieldsNames;
  ...
  public  
  ...
    procedure SetRec (aRec: Pointer);
  ...
  published
  ...
    constructor Create (aOwner: tComponent);
  ...
  end;
implementation
constructor tRttiHelperClass.Create (aOwner: tComponent);
begin
  fCtxt := tRttiContext.Create;
end;
procedure tRttiHelperClass.SetRec (aRec: Pointer);
begin
  private
    fObjectRec.Rec := aRec;
    procedure GetFieldsNames;
end;
procedure tRttiHelperClass.GetFieldsNames;
var f      :  Word    ;
    fields : tRttiType;
begin
  with fRttiContext do begin
        RttiType := GetType (fObjRec.ClassType);
        Fields   := RttiType.GetFields;
         for f := Low (fields) to High (fields) fo begin
             if fields[f].GetValue (tObject (fObjRec^)).IsArray  then // this works
                ...
             if fields[f].GetValue (tObject (fObjRec^)).IsObject then // this works
                ...
             if fields[f].GetValue (tObject (fObjRec^)).IsRecord then // "undeclared identifier IsRecord"
                ...
  end;
end;
end.

I know that in order to work with Records, I must use tRttiRecordType, but I couldn't find the right way to do this. How is the correct code for determining if some field is a Record? Thanks.

user2383818
  • 709
  • 1
  • 8
  • 19

1 Answers1

2

Try this instead:

if fields[f].FieldType.IsRecord then

From System.Rtti.TRttiField.FieldType and System.Rtti.TRttiType.IsRecord.


Now the underlying problem here is you cannot resolve the record fields from an untyped pointer. In order to do something like that, pass your record as a TValue.

procedure SetRec( aRec: TValue);

Call it this way:

SetRec(TValue.From(MyRec));

For a more complete tutorial how to do this and resolve the contents of a record, see Convert Record to Serialized Form Data for sending via HTTP.

Passing TValue works with classes and other types as well.

Community
  • 1
  • 1
LU RD
  • 34,438
  • 5
  • 88
  • 296
  • I've tried those, but since fields[f] is infact a pointer, it returns a `tkPointer`. There must be a way to check the Record that is pointed by fields[f]. – user2383818 Nov 09 '14 at 21:23
  • Ahh misread the question. There is no RTTI available for records this way. You must pass the type of the record to your helper. – LU RD Nov 09 '14 at 21:48