2016-11-01 2 views
0

Ich habe eine TRttiProperty Variable aRttiProperty genannt, die unter der Eigenschaft verweist:RTTI: Wie bekomme ich den Objektzeiger eines Feldes?

Tsubscription = class(TMyObject) 
private 
    fBilling: TMyObject; 
public 
    property billing: TMyObject read fBilling; // << aRttiProperty point to this member 
end; 

Nun, wie kann ich das fBilling Objektzeiger aus aRttiProperty extrahieren?

Ich versuche, es so zu tun, aber es funktioniert nicht:

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

Es ist das Objekt Mutter TSubscription Rückkehr anstelle des fbilling Feldobjekt.

+0

Gut, das nur übertrieben, wenn man nur verwenden kann, 'Ergebnis: = MySubscriptionInstance.Billing;' statt. –

+0

@Remy - Meine Vermutung wäre Loki will auf das Feld schreiben. –

+0

@SertacAkyuz: Wenn er die Speicheradresse des 'fBilling'-Feldes selbst benötigt, ist das Durchlaufen von' TRttiProperty' nicht der richtige Weg (außer man tippt ihn in 'TRttiInstanceProperty' und dekodiert dessen' PropInfo ^. SetProc-Wert). Eine bessere Option wäre, den Offset des Feldes "fBilling" innerhalb der Klasse "Tsubscription" zu erhalten, indem man 'aRttiType.GetField ('fBilling'). Offset '(wobei' aRttiType 'die Klasse' TSubscription 'darstellt) und dann fügen Sie diesen Offset der Startspeicheradresse eines Tsubscription-Objekts hinzu. –

Antwort

4

Der Code, den Sie in Ihrer Frage angezeigt haben, ist vollkommen in Ordnung (vorausgesetzt, Sie beheben Ihre Tsubscription Klassendeklaration mit der Methode). Der getfBillingObj() Code, den Sie zeigte gibt den richtigen Objektzeiger, wie durch den folgenden Code gezeigt:

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; 

Davon abgesehen, ist es nicht notwendig, RTTI in dieser Situation zu verwenden, da TSubscription direkte hat Zugang zu seinen eigenen internen Feldern:

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

Aber auch das ist überflüssig, da die billing Eigenschaft publi ist c. Jeder Anrufer kann nur verwenden, um die billing Eigenschaft als Service-Leistung:

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; 
+0

Ich habe nicht erkannt, dass der Code, der versucht, den Zeiger zu erhalten, in der Klasse war, die es als sein Feld hat. Render RTTI ziemlich redundant .. –

+1

Danke remy! perfekte Antwort ... Ich habe den Bug in meinem Code dank Ihrer Bestätigung gefunden, dass aRttiProperty.GetValue (Self) .AsType ; ist der gute Weg :) in der Tat tat ich Fbilling: = TMyObject (Self); anstelle von Fbilling: = TMyObject.create (Self); .... dummer "visueller" Fehler :( – loki

Verwandte Themen