2009-10-14 42 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