2009-10-14 30 views
7

使用Typinfo单元的多层次出版类,很容易枚举属性,如下面的代码片段所示:发现其中一个物业首次与继承

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; 

不过,我需要的是人物从每个属性继承的确切类。 例如在TControl中,Tag属性来自TComponent,它给它一个1的继承深度(0是在TControl本身中声明的属性,例如Cursor)。

如果我知道哪个类首先定义了属性,则计算继承深度很容易。就我的目的而言,无论财产第一次获得发布可见性的地方都是它首次出现的地方。

我正在使用德尔福2007年。请让我知道是否需要更多的细节。所有的帮助将不胜感激。

回答

4

这适用于我。
的关键是从通过儿童传递得到父母的所属类别所属类别

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

啊......我明白了。希望有一个更直接的方式(例如与VMT搞混),但这绝对有效。幸运的是效率目前并不是我主要关心的问题。感谢您的快速回答 - 您的解决方案绝对在* direct *框之外,我被卡住了。 – Atorian 2009-10-14 11:32:53

2

我不知道,如果你能找到这个使用RTTI可以在Delphi 2007中TComponent树大多数属性声明为保护在原始类中,然后重新声明为已发布进一步向下,并且您只有已发布成员的RTTI。

我很正确地描述一些与Lieven的解决方案非常相似的东西,当我看到他击败了我时。这将找到属性发布的第一个类,如果这是您要查找的内容,但它不会找到该属性最初声明的位置。如果您需要,您需要Delphi 2010的扩展RTTI。

+0

我忘记了**发布的**部分,您是正确的离场。底线:如果**属性最初并未在已发布部分中声明,则无法使用RTTI **在Delphi 2007中最初声明该属性的类。 – 2009-10-14 11:39:49

+0

对,关于保护vs发布,没关系。我只用TControl作为例子。我需要这个工作在一个自定义组件的大树上。它们都有许多已发布的属性,并且通常具有非常深的继承级别,但它们都不会改变属性的可见性。就我而言,无论财产第一次获得发布可视性的地方是它最初出现的地方。希望我能遵循这个规则来保持简单。 – Atorian 2009-10-14 11:47:30