鉴于下面的代码片段,使用GetPropValue(MyComponent,'MySubComponent.Prop1')
会引发EPropertyError异常。
如何使用GetPropValue / SetPropValue检索或设置SubProperties的值?
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;
答案 0 :(得分:6)
正如Robert所说,不支持点符号,但您可以使用RTTI轻松创建设置或获取子属性值的函数。检查此样本
{$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.
答案 1 :(得分:4)
不支持您在问题中使用的点符号。
您需要获取SubComponent的值,然后对各个属性执行Set and Get。
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;
TypInfo.pas方法仅适用于已发布的属性,您可以使用RTTI.pas方法获取公共属性。