【问题标题】:Discovering the class where a property is first published with multiple levels of inheritance发现具有多个继承级别的属性首次发布的类
【发布时间】:2010-12-06 15:23:59
【问题描述】:

使用 Typinfo 单元,很容易枚举属性,如下面的 sn-p 所示:

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。如果需要更多详细信息,请告诉我。我们将不胜感激。

【问题讨论】:

    标签: delphi properties enumeration rtti


    【解决方案1】:

    这对我有用。
    关键是从传递的子 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;
    

    【讨论】:

    • 啊...我明白了。希望有更直接的方式(例如搞乱 VMT),但这绝对有效。幸运的是,效率并不是我目前最关心的问题。感谢您的快速回答 - 您的解决方案绝对超出了我所困的 直接 框。
    【解决方案2】:

    我不知道您是否可以使用 Delphi 2007 中提供的 RTTI 找到它。TComponent 树中的大多数属性在原始类中声明为 protected,然后重新声明为 已发布 进一步向下,并且您只有已发布成员的 RTTI。

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

    【讨论】:

    • 我忘记了 published 部分,你说得对。底线:使用 RTTI if 无法在 Delphi 2007 中获取最初声明该属性的类,该属性最初未在已发布部分中声明。
    • 对,关于受保护与已发布,没关系。我仅以 TControl 为例。我需要它来处理自定义组件的大树。它们都具有许多已发布的属性,并且通常具有非常深的继承级别,但它们都不会改变属性的可见性。就我而言,财产首次获得公开可见性的地方就是它首次出现的地方。希望我可以遵循这个规则来保持简单。
    猜你喜欢
    • 1970-01-01
    • 2012-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-28
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    相关资源
    最近更新 更多