Search code examples
delphirtti

How do I assign defaults to a CLASS' properties at runtime?


Inspired by this question ("How to get default value for property using RTTI)

I thought of how to use the information in there to have a routine that could assign default values to all properties of a class on demand.

See my solution in the answer...


Solution

  • USES System.RTTI;
    
    TYPE
      TPropertyHelper       = CLASS HELPER FOR TRttiProperty
                                FUNCTION    IsOrdinal : BOOLEAN; INLINE;
                                FUNCTION    Default : TValue;
                                FUNCTION    HasDefault : BOOLEAN;
                              END;
    
    { TPropertyHelper }
    
    FUNCTION TPropertyHelper.Default : TValue;
      VAR
        DEF : INTEGER;
    
      BEGIN
        IF Self IS TRttiInstanceProperty THEN
          DEF:=TRttiInstanceProperty(Self).Default
        ELSE
          DEF:=0;
        Result:=TValue.FromOrdinal(PropertyType.Handle,DEF)
      END;
    
    FUNCTION TPropertyHelper.HasDefault : BOOLEAN;
      BEGIN
        Result:=IsOrdinal AND (Self IS TRttiInstanceProperty) AND (Default<>INTEGER($80000000))
      END;
    
    FUNCTION TPropertyHelper.IsOrdinal : BOOLEAN;
      BEGIN
        Result:=PropertyType.IsOrdinal
      END;
    
    PROCEDURE AssignDefaults(CONST [ref] O : TObject ; IncludeInherited : BOOLEAN = TRUE);
      TYPE
        TRttiProperties     = TArray<TRttiProperty>;
    
      VAR
        CTX                 : TRttiContext;
        ClassType           : TRttiType;
        Properties          : TRttiProperties;
        P                   : TRttiProperty;
    
      BEGIN
        CTX:=TRttiContext.Create;
        ClassType:=CTX.GetType(O.ClassType);
        IF IncludeInherited THEN Properties:=ClassType.GetProperties ELSE Properties:=ClassType.GetDeclaredProperties;
        FOR P IN Properties DO IF P.IsWritable AND P.HasDefault THEN P.SetValue(O,P.Default)
      END;