[已编辑] 我试图让 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 个声明的属性。
有任何想法吗?