Delphi 为继承的属性创建属性

Delphi 为继承的属性创建属性,delphi,inheritance,attributes,delphi-2010,Delphi,Inheritance,Attributes,Delphi 2010,[编辑]我正试图让RTTI识别TList泛型类的“Items”属性,以便对其应用属性。我已经编写了一个控制台应用程序,在这里输出RTTI属性: program RTTIAttributes; {$APPTYPE CONSOLE} uses Classes, Generics.Collections, RTTI, SysUtils; type TDataMember = class(TCustomAttribute); TCustomer = class pr

[编辑]我正试图让RTTI识别TList泛型类的“Items”属性,以便对其应用属性。我已经编写了一个控制台应用程序,在这里输出RTTI属性:

program RTTIAttributes;

{$APPTYPE CONSOLE}

uses
  Classes,
  Generics.Collections,
  RTTI,
  SysUtils;

type

  TDataMember = class(TCustomAttribute);

  TCustomer = class
  private
    FName: string;
  public
    [TDataMember]
    property Name: string read FName write FName;  // <- attribute IS recognised by RTTI
  end;

  { inheritance tree: TList<T> -> TObjectList<T> -> TCustomerList
  Here are the base properties declared in TList<T>
  TList<T> = class(TEnumerable<T>)
  ...
  public
    property Capacity: Integer read GetCapacity write SetCapacity;
    property Count: Integer read FCount write SetCount;
    property Items[Index: Integer]: T read GetItem write SetItem; default;   <- not recognised as RTTI property...!
    property OnNotify: TCollectionNotifyEvent<T> read FOnNotify write FOnNotify;
  end;
  }

  TCustomerList = class(TObjectList<TCustomer>)
  public
    //[TDataMember]
    property Items;  // <- inherited property, but NOT recognised by RTTI & hence cannot inspect attributes
  end;

procedure DoRTTIObject(AObject: TObject);
var
  LContext: TRttiContext;
  LProp: TRttiProperty;
  LAttr: TCustomAttribute;
begin
  LContext := TRttiContext.Create;
  try
    Writeln('Process Class: ' + AObject.ClassName);
    for LProp in LContext.GetType(AObject.ClassType).GetProperties do
    begin
      Writeln('Found Property: ' + AObject.ClassName + '.' + LProp.Name);
      for LAttr in LProp.GetAttributes do
        if LAttr is TDataMember then
          Writeln(AObject.ClassName + '.' + LProp.Name + ': HAS TDataMember attribute')
        else
          Writeln(AObject.ClassName + '.' + LProp.Name + ': DOES NOT HAVE TDataMember attribute');
    end;
    Writeln('');
  finally
    LContext.Free;
  end;
end;

var
  LList: TCustomerList;
begin

  LList := TCustomerList.Create;
  LList.Add(TCustomer.Create);
  DoRTTIObject(LList);
  DoRTTIObject(LList[0]);

  Readln;
end.
因此,无论出于何种原因,我无法确定,RTTI识别祖先类声明的属性中的3个,而不是4个


有什么想法吗?

什么德尔福版本?将可见性从受保护更改为公共可能还不够。也许您应该将它推广到已发布的版本,并使用经典(非扩展)RTTI.delphi2010。继承的属性(项)已在祖先类中公开。我只是尝试重新声明它并引入一个属性。将其设置为“已发布”无效,会出现错误:E2188已发布属性“Items”不能为数组类型。还有其他想法吗?哦,这是一种数组类型,你想在它上面使用扩展RTTI吗?我建议您放弃x阵列,使用集合。如果您不熟悉
TCollectionItem
,那么这是嵌入大量灵活对象并为其提供经典标准rtti的经典rtti方法。因为它是类类型,所以属性可以工作。我从TObjectList开始下降,所以我认为它使用了TEnumerable。我不想更改项目的基本类型,我只想能够向属性添加一个属性,我可以使用RTTI检测到该属性。我认为遗漏所有这些信息会使您的问题难以回答。也许可以发布一个显示此问题的类型的最小完整示例,而不是上面的非类型化代码。TCustomerList是TObjectList这一事实与属性项无关,它的类型是什么?
Process Class: TCustomerList
Found Property: TCustomerList.OwnsObjects
Found Property: TCustomerList.Capacity
Found Property: TCustomerList.Count
Found Property: TCustomerList.OnNotify

Process Class: TCustomer
Found Property: TCustomer.Name
TCustomer.Name: HAS TDataMember attribute