2009-10-14 2 views
7

Mit der Typinfo Einheit veröffentlicht wird, ist es einfach, Eigenschaften aufzuzählen, wie im folgenden Ausschnitt gesehen:die Klasse zu entdecken, wo ein Objekt zunächst mit mehreren Ebenen der Vererbung

procedure TYRPropertiesMap.InitFrom(AClass: TClass; InheritLevel: Integer = 0); 
var 
    propInfo: PPropInfo; 
    propCount: Integer; 
    propList: PPropList; 
    propType: PPTypeInfo; 
    pm: TYRPropertyMap; 
    classInfo: TClassInfo; 
    ix: Integer; 

begin 
    ClearMap; 

    propCount := GetPropList(PTypeInfo(AClass.ClassInfo), propList); 
    for ix := 0 to propCount - 1 do 
    begin 
    propInfo := propList^[ix]; 
    propType := propInfo^.PropType; 

    if propType^.Kind = tkMethod then 
     Continue; // Skip methods 
    { Need to get GetPropInheritenceIndex to work 
    if GetPropInheritenceIndex(propInfo) > InheritLevel then 
     Continue; // Dont include properties deeper than InheritLevel 
    } 
    pm := TYRPropertyMap.Create(propInfo.Name); 
    FList.Add(pm); 
    end; 
end; 

Aber was ich brauche, ist zu Figur aus der genauen Klasse, aus der jede Eigenschaft erbt. Zum Beispiel in TControl, die Tag-Eigenschaft kommt von TComponent, was ihm eine Vererbungstiefe von 1 gibt (0 ist eine Eigenschaft, die in TControl selbst deklariert wird, wie zum Beispiel Cursor).

Berechnung der Vererbung Tiefe ist einfach, wenn ich weiß, welche Klasse zuerst die Eigenschaft definiert. Für meine Zwecke ist, wo ein Objekt zuerst veröffentlicht Sichtbarkeit gewonnen hat, wo es zuerst erschien.

Ich benutze Delphi 2007. Bitte lassen Sie mich wissen, wenn mehr Details erforderlich sind. Alle Hilfe wird geschätzt.

Antwort

4

Das funktioniert für mich.
Der Kernpunkt ist immer die Typeinfo der Eltern aus dem Durch Kind weitergegeben Typeinfo

procedure InheritanceLevel(AClassInfo: PTypeInfo; const AProperty: string; var level: Integer); 
var 
    propInfo: PPropInfo; 
    propCount: Integer; 
    propList: PPropList; 
    ix: Integer; 
begin 
    if not Assigned(AClassInfo) then Exit; 
    propCount := GetPropList(AClassInfo, propList); 
    for ix := 0 to propCount - 1 do 
    begin 
    propInfo := propList^[ix]; 
    if propInfo^.Name = AProperty then 
    begin 
     Inc(level); 
     InheritanceLevel(GetTypeData(AClassInfo).ParentInfo^, AProperty, level) 
    end; 
    end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    level: Integer; 
begin 
    level := 0; 
    InheritanceLevel(PTypeInfo(TForm.ClassInfo), 'Tag', level); 
end; 
+0

Ah ... Ich verstehe. Hatte auf einen direkteren Weg gehofft (zum Beispiel mit der VMT herumspielen), aber das funktioniert definitiv. Zum Glück geht es mir im Moment nicht um Effizienz. Danke für die schnelle Antwort - deine Lösung ist definitiv außerhalb der * direct * Box, in der ich steckte. – Atorian

2

Ich weiß nicht, ob Sie dies mit der RTTI in Delphi 2007. Die meisten Objekte im TComponent Baum als deklariert finden geschützt in der ursprünglichen Klasse, und dann als veröffentlicht weiter unten reklamiert, und Sie haben nur RTTI für veröffentlichte Mitglieder.

Ich hatte recht, etwas zu beschreiben, das Lievens Lösung sehr ähnlich ist, als ich sah, dass er mich dazu schlagen würde. Dies wird die erste Klasse finden, in der die Eigenschaft veröffentlicht wurde, wenn Sie das suchen, aber sie wird nicht finden, wo die Eigenschaft ursprünglich deklariert wurde. Wenn Sie das möchten, brauchen Sie die erweiterte RTTI von Delphi 2010.

+0

Ich habe den ** veröffentlichten ** Teil vergessen, du bist ganz nebenbei. Fazit: Es ist nicht möglich, die Klasse zu erhalten, in der die Eigenschaft ursprünglich mit Delphi 2007 mit RTTI deklariert wurde **, wenn die Eigenschaft ursprünglich nicht im veröffentlichten Abschnitt deklariert wurde. –

+0

Richtig, in Bezug auf geschützte vs veröffentlicht, das ist in Ordnung. Ich habe nur TControl als Beispiel benutzt. Ich brauche das, um an einem großen Baum von benutzerdefinierten Komponenten zu arbeiten. Alle von ihnen haben viele veröffentlichte Eigenschaften und oft sehr tiefe Vererbungsebenen, aber keiner von ihnen ändert die Eigenschaftensichtbarkeit. Soweit es mich betrifft, ist ein Ort, an dem er zuerst veröffentlicht wurde, dort, wo er zuerst erschien. Hoffentlich kann ich dieser Regel folgen, um die Dinge einfach zu halten. – Atorian

Verwandte Themen