'Delphi - recursively checking class properties attributes

I have tree of class to hold some program parameters. Sometimes there is one level, but sometimes the may child objects, or even children lists with objects etc ... I would like to check / apply some changes to properties using attributes. It's easy at the first level through rtti. I'm struggling to do so recursively : how can I retrieve children instances to apply the check procedure ?

Sort of:



    procedure check(poInstance : TConfClass) ;
    var
      c : TRTTIContext;
      f : TRTTIField;
      p : TRTTIProperty;
      t: TRTTIType;
      a : TCustomAttribute;
    begin
    
      c := TRTTIContext.Create;
    
      for p in c.GetType(poValue.ClassType).GetProperties do
        begin
         
          if  p.PropertyType.TypeKind = tkClass then
            begin
              if Copy(p.PropertyType.ToString,1,5) = 'TList' then
                begin
                  // loop over the list and if it's an instance of TConfClass then call check with this instance
                end
                else
                  // if it's an instance of TConfclass then call Check(instance)>
    
            end
    
          else begin
    
              for a in p.GetAttributes do begin
                  // check / alter values following attributes
                end;
              end ;
    
            end;
    
        end;
    
      c.Free;
    
    end;

What is the best way to achieve this ?



Solution 1:[1]

I could find a solution



    procedure BeforeSerializeClass(poValue: TObject);
    var
      loContext : TRTTIContext;
      loProp : TRTTIProperty;
      loType : TRTTIType;
      loAttr : TCustomAttribute;
      loMeth : TRTTIMethod;
      loValue : TValue;
      nCnt : integer;
      loTmp : TObject;
    begin
    
      loContext := TRTTIContext.Create;
    
       for loProp in loContext.GetType(poValue.ClassType).GetProperties do
    
       begin
    
          if loProp.PropertyType.TypeKind = tkClass then
          begin
                loTmp := loProp.GetValue(poValue).AsObject ;
                loType := loCOntext.GetType(loTmp.ClassInfo);
                loMeth := loType.GetMethod('ToArray');
                if Assigned(loMeth) then begin
                     loValue := loMeth.Invoke(loTmp, []);
                     Assert(loValue.IsArray);
                     nCnt := loValue.GetArrayLength;
    
                     while nCnt > 0 do begin
                       Dec(nCnt);
                       BeforeSerializeClass(loValue.GetArrayElement(ncnt).AsObject);
                     end;
    
              end
              else begin
                  BeforeSerializeClass(loProp.GetValue(poValue).AsObject)  ;
              end;
    
          end
    
          else begin
    
              for loAttr in loProp.GetAttributes do begin
    
                if loAttr is TCrypt  then begin
                    (loAttr as TCrypt).Value := loProp.GetValue(poValue).AsString;
                    loProp.SetValue(poValue,(loAttr as TCrypt).encrypt);
                end;
    
    
              end ;
    
          end;
    
        end;
    
      loContext.Free;
    
    end;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 halted