2009-10-14 20 views
7

En utilisant l'unité TypInfo, il est facile d'énumérer les propriétés comme on le voit dans l'extrait suivant:Découverte de la classe où une propriété est d'abord publié avec plusieurs niveaux d'héritage

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; 

Cependant, ce que je dois est à la figure la classe exacte à partir de laquelle chaque propriété hérite. Par exemple dans TControl, la propriété Tag provient de TComponent, ce qui lui donne une profondeur d'héritage de 1 (0 étant une propriété déclarée dans TControl lui-même, tel que Cursor).

Il est facile de calculer la profondeur d'héritage si je sais quelle classe a défini la propriété en premier. Pour mes buts, partout où une propriété a d'abord gagné la visibilité publiée est l'endroit où elle est apparue. J'utilise Delphi 2007. S'il vous plaît laissez-moi savoir si plus de détails sont nécessaires. Toute aide sera appréciée.

Répondre

4

Cela fonctionne pour moi.
Le point crucial est d'obtenir TypeInfo du parent du passé par l'enfant 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 ... je vois. Espérait un moyen plus direct (par exemple, avec le VMT), mais cela fonctionne définitivement. Heureusement, l'efficacité n'est pas ma principale préoccupation en ce moment. Merci pour la réponse rapide - votre solution est définitivement en dehors de la boîte * direct * dans laquelle j'ai été coincé. – Atorian

2

Je ne sais pas si vous pouvez trouver cela en utilisant le RTTI disponible en Delphi 2007. La plupart des propriétés dans l'arbre TComponent sont déclarés comme protégé dans la classe d'origine, puis redéclaré comme publié plus bas, et vous avez seulement RTTI pour les membres publiés.

J'avais raison de décrire quelque chose de très similaire à la solution de Lieven quand j'ai vu qu'il me battait dessus. Cela trouvera la première classe où la propriété a été publiée, si c'est ce que vous recherchez, mais elle ne trouvera pas où la propriété a été déclarée à l'origine. Vous avez besoin du RTTI étendu de Delphi 2010 si vous le souhaitez.

+0

J'ai oublié la partie ** publiée **, vous avez raison. Bottom line: il n'est pas possible d'obtenir la classe où la propriété a été déclarée à l'origine avec Delphi 2007 en utilisant RTTI ** si ** la propriété n'a pas été déclarée à l'origine dans la section publiée. –

+0

Droit, en ce qui concerne protégé contre publié, c'est correct. J'ai seulement utilisé TControl comme exemple. J'ai besoin de cela pour travailler sur un grand arbre de composants personnalisés. Tous ont de nombreuses propriétés publiées et des niveaux d'héritage souvent très profonds, mais aucun d'entre eux ne modifie la visibilité des propriétés. En ce qui me concerne, partout où une propriété a acquis la visibilité publiée, c'est là qu'elle est apparue la première fois. J'espère que je peux suivre cette règle pour garder les choses simples. – Atorian