Код, который вы указали в своем вопросе, отлично (при условии, что вы исправили объявление класса 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;
Ну это просто перебор, когда вы можете просто использовать 'Result: = MySubscriptionInstance.Billing;' вместо этого. –
@Remy - Думаю, Локи хочет написать на поле. –
@SertacAkyuz: Если ему нужен адрес памяти самого поля 'fBilling', то через' TRttiProperty' это не правильный способ сделать это (если вы не наберете его в 'TRttiInstanceProperty', а затем декодируете его' PropInfo ^. SetProc'). Лучшим вариантом было бы получить смещение поля 'fBilling' в классе' Tsubscription' с помощью 'aRttiType.GetField ('fBilling'). Offset' (где' aRttiType' представляет класс 'TSubscription'), а затем добавьте это смещение к начальному адресу памяти объекта 'Tsubscription'. –