6

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 を返すだけです。

4

3 に答える 3

6

もう 1 つのオプションは、 の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.
于 2012-07-05T21:50:55.733 に答える
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;
于 2012-07-05T20:29:07.263 に答える
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.
于 2012-07-05T21:43:27.050 に答える