RTTI & Attributes

Run-Time Type Information lets a program inspect types at run time: class names, published properties, enumeration names, method addresses, and (in extended RTTI) fields, methods, and attributes.

33.1 What is RTTI?

Run-Time Type Information lets a program inspect types at run time: class names, published properties, enumeration names, method addresses, and (in extended RTTI) fields, methods, and attributes. It powers the form designer, .lfm/.dfm streaming, data binding, serialization libraries, ORMs, and test frameworks.

Classic (published members, enums, sets) Extended (all visibility levels, methods, invoke) Delphi 2010+; FPC trunk (partial) System.Rtti (Delphi), Rtti (FPC)

Delphi 2010+; FPC trunk with {$modeswitch prefixedattributes}

33.2 Classic RTTI with TypInfo (Delphi and FPC)

(In Delphi the type names read string and Integer.)

program PublishedRtti;
{$mode objfpc}{$H+}
uses SysUtils, Variants, TypInfo;

type
  {$M+}                          // generate RTTI for published members
  TPerson = class
  private
    FName: string;
    FAge: Integer;
    FActive: Boolean;
  published
    property Name: string read FName write FName;
    property Age: Integer read FAge write FAge;
    property Active: Boolean read FActive write FActive;
  end;
  {$M-}

var
  P: TPerson;
  Props: PPropList;
  Count, I: Integer;
begin
  P := TPerson.Create;
  try
    SetPropValue(P, 'Name', 'Ada');               // set by name (Variant-based)
    SetOrdProp(P, 'Age', 36);
    SetEnumProp(P, 'Active', 'True');

    Count := GetPropList(P, Props);
    try
      for I := 0 to Count - 1 do
        Writeln(Props^[I]^.Name, ' : ', Props^[I]^.PropType^.Name,
                ' = ', GetPropValue(P, Props^[I]^.Name));
    finally
      FreeMem(Props);
    end;
  finally
    P.Free;
  end;
end.
Name : AnsiString = Ada
Age : LongInt = 36
Active : Boolean = True

33.3 Extended RTTI (Delphi)

By default Delphi generates extended RTTI for public and published properties and methods, and for all fields; {$RTTI EXPLICIT ...} changes this (often used to shrink executables).

uses System.Rtti;

procedure DumpObject(Obj: TObject);
var
  Ctx: TRttiContext;
  T: TRttiType;
  Prop: TRttiProperty;
  M: TRttiMethod;
begin
  Ctx := TRttiContext.Create;
  T := Ctx.GetType(Obj.ClassType);
  Writeln('Type: ', T.Name);
  for Prop in T.GetProperties do
    if Prop.IsReadable then
      Writeln('  ', Prop.Name, ' = ', Prop.GetValue(Obj).ToString);
  for M in T.GetDeclaredMethods do
    Writeln('  method ', M.Name);
  M := T.GetMethod('Describe');
  if Assigned(M) then
    Writeln(M.Invoke(Obj, []).ToString);       // dynamic invocation
end;

33.4 Custom attributes (Delphi)

The Attribute suffix can be omitted when applying ([MaxLength(40)]). Attributes are used by DUnitX ([Test]), JSON serializers ([JSONName('id')]), ORMs ([Table('customers')]), and REST frameworks.

uses System.Rtti, System.SysUtils;

type
  MaxLengthAttribute = class(TCustomAttribute)
  private
    FLength: Integer;
  public
    constructor Create(ALength: Integer);
    property Length: Integer read FLength;
  end;

  RequiredAttribute = class(TCustomAttribute);

  TCustomer = class
  private
    FName: string;
    FEmail: string;
  public
    [Required, MaxLength(40)]
    property Name: string read FName write FName;
    [MaxLength(80)]
    property Email: string read FEmail write FEmail;
  end;

constructor MaxLengthAttribute.Create(ALength: Integer);
begin
  inherited Create;
  FLength := ALength;
end;

function Validate(Obj: TObject): TArray<string>;
var
  Ctx: TRttiContext;
  Prop: TRttiProperty;
  Attr: TCustomAttribute;
  S: string;
begin
  Result := nil;
  for Prop in Ctx.GetType(Obj.ClassType).GetProperties do
  begin
    S := Prop.GetValue(Obj).AsString;
    for Attr in Prop.GetAttributes do
      if (Attr is RequiredAttribute) and (S = '') then
        Result := Result + [Prop.Name + ' is required']
      else if (Attr is MaxLengthAttribute) and
              (S.Length > MaxLengthAttribute(Attr).Length) then
        Result := Result + [Format('%s exceeds %d charact
…