RTTI:如何获取字段的对象指针?

时间:2016-11-01 21:46:52

标签: delphi rtti

我有一个名为TRttiProperty的{​​{1}}变量,指向下面的属性:

aRttiProperty

现在,如何从Tsubscription = class(TMyObject) private fBilling: TMyObject; public property billing: TMyObject read fBilling; // << aRttiProperty point to this member end;

中提取fBilling对象指针

我尝试这样做,但它不起作用:

aRttiProperty

它返回父function Tsubscription.getfBillingObj(const aRttiProperty: TRttiProperty): TMyObject begin Result := aRttiProperty.GetValue(Self).AsType<TMyObject>; end; 个对象而不是TSubscription字段对象。

1 个答案:

答案 0 :(得分:5)

您在问题中显示的代码非常好(假设您修复了Tsubscription类声明以包含getfBillingObj()方法)。您显示的getfBillingObj()代码返回正确的对象指针,如以下代码所示:

uses
  System.Rtti;

type
  TMyObject = class
  public
    Name: string;
    constructor Create(const aName: string);
  end;

  Tsubscription = class(TMyObject)
  private
    fBilling: TMyObject;
  public
    constructor Create(const aName: string);
    destructor Destroy; override;
    function getfBillingObj(const aRttiProperty: TRttiProperty): TMyObject;
    property billing: TMyObject read fBilling;
  end;

constructor TMyObject.Create(const aName: string);
begin
  inherited Create;
  Name := aName;
end;

constructor Tsubscription.Create(const aName: string);
begin
  inherited Create(aName);
  fBilling := TMyObject.Create('bill');
end;

destructor Tsubscription.Destroy;
begin
  fBilling.Free;
end;

function Tsubscription.getfBillingObj(const aRttiProperty: TRttiProperty): TMyObject;
begin
  Result := aRttiProperty.GetValue(Self).AsType<TMyObject>;
end;

var
  Ctx: TRttiContext;
  prop: TRttiProperty;
  sub: Tsubscription;
  bill: TMyObject;
begin
  sub := Tsubscription.Create('sub');
  try
    prop := ctx.GetType(Tsubscription).GetProperty('billing');
    bill := sub.getfBillingObj(prop);
    // bill.Name is 'bill' as expected...
  finally
    sub.Free;
  end;
end;

话虽如此,在这种情况下没有必要使用RTTI,因为TSubscription可以直接访问自己的内部字段:

function TSubscription.getfBillingObj: TMyObject 
begin
  Result := fBilling;
end; 

但即使这是多余的,因为billing属性是公开的。任何调用者都可以按原样使用billing属性:

var
  sub: Tsubscription;
  bill: TMyObject;
begin
  sub := Tsubscription.Create('sub');
  try
    bill := sub.billing;
    // bill.Name is 'bill' as expected...
  finally
    sub.Free;
  end;
end;