2

[已编辑] 我试图让 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.

上面的控制台应用程序产生以下输出:

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

因此,无论出于何种原因,我无法确定,RTTI 识别祖先类的 3 个但不是 4 个声明的属性。

有任何想法吗?

4

0 回答 0