2009-10-14 2 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).

Вычисление глубины наследования легко, если я знаю, какой класс сначала определил свойство. Для моих целей везде, где свойство сначала получило опубликованную видимость, это место, где оно впервые появилось.

Я использую Delphi 2007. Пожалуйста, дайте мне знать, если требуется более подробная информация. Вся помощь будет оценена.

ответ

4

Это работает для меня.
Затруднение получает родитель TypeInfo из пропущенных через ребенок 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

А ... Я вижу. Надеюсь на более прямой путь (например, возиться с VMT), но это определенно работает. К счастью, эффективность в настоящее время не является моей главной задачей. Спасибо за быстрый ответ - ваше решение, безусловно, находится за пределами * прямого * ящика, в который я застрял. – Atorian

2

Я не знаю, если вы можете найти это, используя доступную RTTI в Delphi 2007. Большинство свойства в дереве TComponent объявлены в защищенный в первоначальном классе, а затем обновленный как опубликован ниже, и у вас есть только RTTI для опубликованных членов.

Я был прав, чтобы описать что-то очень похожее на решение Ливена, когда увидел, что он избил меня. Это найдет первый класс, в котором было опубликовано свойство, если это то, что вы ищете, но не найдет, где было объявлено свойство. Вам нужен расширенный RTTI Delphi 2010, если вы этого хотите.

+0

Я забыл о ** опубликованной ** части, вы прямо противоположны. Итог: невозможно получить класс, в котором свойство было первоначально объявлено с помощью Delphi 2007 с использованием RTTI **, если ** свойство первоначально не было объявлено в опубликованном разделе. –

+0

Правильно, в отношении защищенных и опубликованных, все в порядке. В качестве примера я использовал только TControl. Мне нужно, чтобы это работало на большом дереве пользовательских компонентов. Все они имеют много опубликованных свойств и часто очень глубокие уровни наследования, но ни одна из них не меняет видимость свойств. Насколько мне известно, везде, где собственность впервые получила опубликованную визуальность, это место, где оно впервые появилось. Надеюсь, я смогу следовать этому правилу, чтобы все было просто. – Atorian

Смежные вопросы