Search code examples
delphirtti

Collect all descendants of a class using RTTI in Delphi 10.3.3


I need TClass for all descendants of a base TClass.

I tried this code:

type
  TClassList = TList<TClass>;

class procedure TClassUtility.collectDescendantClasses( ancestorClass_ : TClass; descendantClasses_ : TClassList );
var
  ctx: TRttiContext;
  list : TArray<TRttiType>;
  typ: TRttiType;
begin
  if ( descendantClasses_ <> NIL ) then
  begin
    ctx := TRttiContext.Create;
    try
      list := ctx.GetTypes;
      for typ in list do
      begin
        if ( typ.TypeKind = tkInstance ) then
          if ( ( ancestorClass_ = NIL ) or ( typ.ClassType.InheritsFrom( ancestorClass_ ) ) ) then
            descendantClasses_.Add( typ.ClassType );
      end;
    finally
      ctx.Free
    end;
  end else
    raise Exception.Create('' );
end;

It collects nothing. The typ.ClassType.QualifiedClassName always TRTTIInstanceType for all list item. typ.QualifiedName stores the right type names. But how could I access the TClass called typ.QualifiedName if typ.ClassType is the record itself?

I can't figure it out using the Delphi help.


Solution

  • You need to see if typ is of type TRttiInstanceType and if so you can access its MetaclassType property:

    for typ in list do
      if typ is TRttiInstanceType then
        if (ancestorClass_ = nil) or TRttiInstanceType(typ).MetaclassType.InheritsFrom(ancestorClass_) then
          descendantClasses_.Add(TRttiInstanceType(typ).MetaclassType);