使用Delphi 2010和RTTI,我知道如何获取对象的类类型以及如何获取/设置对象属性的值和类型,但是如何确定属性来自继承链中的哪个类?我想以不同于主类的方式使用基类的属性。
考虑以下代码:
TClassBase = class(TObject)
published
property A: Integer;
end;
TClassDescendant = class(TClassBase)
published
property B: Integer;
end;
procedure CheckProperties(Obj: TObject);
var
ctx: TRttiContext;
objType: TRttiType;
Prop: TRttiProperty;
begin
ctx := TRttiContext.Create;
objType := ctx.GetType(Obj.ClassInfo);
for Prop in objType.GetProperties do begin
if Prop.GetClassType is TClassBase then
// do something special with base class properties
else
// standard functionality on all other properties
end;
end;
问题是属性没有GetClassType。 ClassType只返回TRttiInstancePropertyEx而不是属性所属类的名称。
答案 0 :(得分:5)
另一个选项是使用Parent
的TRttiProperty
属性,从这里您可以访问属性所属的类。
{$APPTYPE CONSOLE}
{$R *.res}
uses
Rtti,
SysUtils;
type
TClassBase = class(TObject)
private
FA: Integer;
published
property A: Integer read FA;
end;
TClassDescendant = class(TClassBase)
private
FB: Integer;
published
property B: Integer read FB;
end;
procedure CheckProperties(Obj: TObject);
var
ctx: TRttiContext;
objType: TRttiType;
Prop: TRttiProperty;
begin
ctx := TRttiContext.Create;
objType := ctx.GetType(Obj.ClassInfo);
for Prop in objType.GetProperties do
if TRttiInstanceType(Prop.Parent).MetaclassType=TClassBase then
Writeln(Format('The property %s is declarated in the TClassBase class',[Prop.Name]))
else
Writeln(Format('The property %s is not declarated in the TClassBase class',[Prop.Name]))
end;
begin
try
//CheckProperties(TClassBase.Create);
CheckProperties(TClassDescendant.Create);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
答案 1 :(得分:2)
我不知道是否可以获得引入属性的类,但是您可以使用常规RTTI来解决您的问题:
begin
...
for Prop in objType.GetProperties do begin
if Assigned(GetPropInfo(TClassBase, Prop.Name)) then
// do something special with base class properties
else
// standard functionality on all other properties
end;
end;
答案 2 :(得分:2)
您可以使用GetDeclaredProperties方法获取当前类中声明的属性,然后与GetProperties方法返回的值进行比较。
试试这个样本。
{$APPTYPE CONSOLE}
{$R *.res}
uses
Rtti,
SysUtils;
type
TClassBase = class(TObject)
private
FA: Integer;
published
property A: Integer read FA;
end;
TClassDescendant = class(TClassBase)
private
FB: Integer;
published
property B: Integer read FB;
end;
procedure CheckProperties(Obj: TObject);
function ExistProp(const PropName:string; List:TArray<TRttiProperty>) : Boolean;
var
Prop: TRttiProperty;
begin
result:=False;
for Prop in List do
if SameText(PropName, Prop.Name) then
begin
Result:=True;
break;
end;
end;
var
ctx: TRttiContext;
objType: TRttiType;
Prop: TRttiProperty;
CurrentClassProps : TArray<TRttiProperty>;
begin
ctx := TRttiContext.Create;
objType := ctx.GetType(Obj.ClassInfo);
CurrentClassProps:=objType.GetDeclaredProperties;
for Prop in objType.GetProperties do
if ExistProp(Prop.Name, CurrentClassProps) then
Writeln(Format('The property %s is declarated in the current %s class',[Prop.Name, obj.ClassName]))
else
Writeln(Format('The property %s is declarated in the base class',[Prop.Name]))
end;
begin
try
//CheckProperties(TClassBase.Create);
CheckProperties(TClassDescendant.Create);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.