Discovering the class where a property is first published with multiple levels of inheritance

扶醉桌前 提交于 2019-12-21 12:20:13

问题


Using the Typinfo unit, it is easy to enumerate properties as seen in the following snippet:

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;

However, what I need is to figure out the exact class from which each property inherits. For example in TControl, the Tag property comes from TComponent, which gives it an inheritance depth of 1 (0 being a property declared in TControl itself, such as Cursor).

Calculating the inheritance depth is easy if I know which class first defined the property. For my purposes, wherever a property first gained published visibility is where it first appeared.

I am using Delphi 2007. Please let me know if more detail is required. All help will be appreciated.


回答1:


This works for me.
The crux is getting the parent's TypeInfo from the passed through child 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;



回答2:


I don't know if you can find this using the RTTI available in Delphi 2007. Most properties in the TComponent tree are declared as protected in the original class, and then redeclared as published further down, and you only have RTTI for published members.

I was right about to describe something very similar to Lieven's solution when I saw that he'd beat me to it. This will find the first class where the property was published, if that's what you're looking for, but it won't find where the property was originally declared. You need Delphi 2010's extended RTTI if you wanted that.



来源:https://stackoverflow.com/questions/1565614/discovering-the-class-where-a-property-is-first-published-with-multiple-levels-o

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!