Get / Set sub properties ussing RTTI

Given the following code snippet, using GetPropValue(MyComponent,'MySubComponent.Prop1') throws an EPropertyError exception. How to get or set SubProperties values ​​using GetPropValue / SetPropValue?

 Type TMySubComponent = class(TInterfacedPersitent) private FProp1: Integer; published property Prop1: integer read FProp1 write FProp1; end; TMyComponent = class(TCompoent) private FMySubComponent : TMySubcomponent; published property MySubComponent: TMySubComponent read FMySubComponent write FMySubComponent ; end; 
+3
source share
2 answers

The dot notation you used in your question is not supported.

You need to get the SubComponent value, and then execute Set and Get on the individual properties.

 var C: TRttiContext; MyComp : TMyComponent; MyCompType : TRttiInstanceType; MySubCompType : TRttiInstanceType; MySubComponentValue : TValue; begin MyComp := TMyComponent.create(Self); ... // RTTI.Pas Method MyCompType := c.GetType(TMyComponent.ClassInfo) as TRttiInstanceType; MySubCompType := c.GetType(TMySubComponent.ClassInfo) as TRttiInstanceType; MySubComponentValue := MyCompType.GetProperty('MySubComponent').GetValue(MyComp); if Not MySubComponentValue.IsEmpty then begin MySubCompType.GetProperty('Prop1').SetValue(MySubComponentValue.AsObject,43); end; //TypInfo.pas Method SubComp := GetObjectProp(MyComp,'MySubComponent'); if Assigned(SubComp) then begin SetPropValue(SubComp,'Prop1',5); prop1Value := GetPropValue(SubComp,'Prop1'); end; end; 

The TypInfo.pas method will only work with published properties; you can get public properties using the RTTI.pas method.

+4
source

According to Robert, dot notation is not supported, but you can easily create a function to set or get a subsite value using 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. 
+6
source

All Articles