user2383818
user2383818

Reputation: 689

How to determine using Rtti, if a field from a class is a Record

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.

Upvotes: 2

Views: 1451

Answers (1)

LU RD
LU RD

Reputation: 34899

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.

Upvotes: 2

Related Questions