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

2 回答 2

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;
于 2009-10-14T11:25:06.793 回答
2

我不知道您是否可以使用 Delphi 2007 中提供的 RTTI 找到这一点。TComponent 树中的大多数属性在原始类中被声明为受保护,然后再被重新声明为已发布,并且您只有发布成员的 RTTI。

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

于 2009-10-14T11:28:36.470 回答