Get/Set sub properties ussing RTTI

前端 未结 2 655
轻奢々
轻奢々 2021-01-06 14:43

Given the following code snippet below, using GetPropValue(MyComponent,\'MySubComponent.Prop1\') raises an EPropertyError exception. How can I retrieve or set t

2条回答
  •  臣服心动
    2021-01-06 14:55

    As Robert says the dot notation is not supported , but you can create easily a function to set or get a sub-property value using the RTTI. check this sample

    {$APPTYPE CONSOLE}
    
    uses
      Rtti,
      Classes,
      SysUtils;
    
    
    Type
      TMySubComponent = class(TInterfacedPersistent)
      private
        FProp1: Integer;
      published
        property Prop1: integer read FProp1 write FProp1;
      end;
    
      TMyComponent = class(TComponent)
      private
        FMySubComponent : TMySubcomponent;
      published
        property MySubComponent: TMySubComponent read FMySubComponent write FMySubComponent ;
      end;
    
    
    
    procedure SetObjValueEx(const ObjPath:string;AInstance:TObject;AValue:TValue);
    Var
     c            : TRttiContext;
     Prop         : string;
     SubProp      : string;
     pm           : TRttiProperty;
     p            : TRttiProperty;
     Obj          : TObject;
    begin
     Prop:=Copy(ObjPath,1,Pos('.',ObjPath)-1);
     SubProp:=Copy(ObjPath,Pos('.',ObjPath)+1);
     c := TRttiContext.Create;
     try
       for pm in c.GetType(AInstance.ClassInfo).GetProperties do
       if CompareText(Prop,pm.Name)=0 then
       begin
         p := c.GetType(pm.PropertyType.Handle).GetProperty(SubProp);
          if Assigned(p) then
          begin
            Obj:=pm.GetValue(AInstance).AsObject;
            if Assigned(Obj) then
              p.SetValue(Obj,AValue);
          end;
          break;
       end;
     finally
       c.Free;
     end;
    end;
    
    
    function GetObjValueEx(const ObjPath:string;AInstance:TObject):TValue;
    Var
     c            : TRttiContext;
     Prop         : string;
     SubProp      : string;
     pm           : TRttiProperty;
     p            : TRttiProperty;
     Obj          : TObject;
    begin
     Prop:=Copy(ObjPath,1,Pos('.',ObjPath)-1);
     SubProp:=Copy(ObjPath,Pos('.',ObjPath)+1);
     c := TRttiContext.Create;
     try
       for pm in c.GetType(AInstance.ClassInfo).GetProperties do
       if CompareText(Prop,pm.Name)=0 then
       begin
         p := c.GetType(pm.PropertyType.Handle).GetProperty(SubProp);
          if Assigned(p) then
          begin
            Obj:=pm.GetValue(AInstance).AsObject;
            if Assigned(Obj) then
              Result:=p.GetValue(Obj);
          end;
          break;
       end;
     finally
       c.Free;
     end;
    end;
    
    Var
      MyComp : TMyComponent;
    begin
      try
         MyComp:=TMyComponent.Create(nil);
         try
           MyComp.MySubComponent:=TMySubComponent.Create;
           //Set the value of the property 
           SetObjValueEx('MySubComponent.Prop1',MyComp,777);
           //Get the value of the property 
           Writeln(Format('The value of MySubComponent.Prop1 is %d',[GetObjValueEx('MySubComponent.Prop1',MyComp).AsInteger]));
         finally
           MyComp.Free;
         end;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
      Readln;
    end.
    

提交回复
热议问题