Given the following code snippet below, using GetPropValue(MyComponent,\'MySubComponent.Prop1\')
raises an EPropertyError exception.
How can I retrieve or set t
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.
The dot notation you used in your question is not supported.
You need to get the Value of the SubComponent, then perform the 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 the public properties with the RTTI.pas method.