Reputation: 13345
I have a TRttiProperty
variable named aRttiProperty
, that points to the property below:
Tsubscription = class(TMyObject)
private
fBilling: TMyObject;
public
property billing: TMyObject read fBilling; // << aRttiProperty point to this member
end;
Now, how can I extract the fBilling
object pointer from aRttiProperty
?
I try to do it like this, but it is not working:
function Tsubscription.getfBillingObj(const aRttiProperty: TRttiProperty): TMyObject
begin
Result := aRttiProperty.GetValue(Self).AsType<TMyObject>;
end;
It's returning the parent TSubscription
object instead of the fbilling
field object.
Upvotes: 0
Views: 1923
Reputation: 595295
The code you showed in your question is perfectly fine (provided you fix your Tsubscription
class declaration to include the getfBillingObj()
method). The getfBillingObj()
code you showed returns the correct object pointer, as demonstrated by the following code:
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;
That being said, it is not necessary to use RTTI in this situation since TSubscription
has direct access to its own internal fields:
function TSubscription.getfBillingObj: TMyObject
begin
Result := fBilling;
end;
But even that is redundant since the billing
property is public. Any caller can just use the billing
property as-is:
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;
Upvotes: 6