可以只循环 class 的声明属性吗?

Possible to loop only declared properties of a class?

扩展的 RTTI 具有 GetDeclaredProperties 功能,这正是我所需要的,但是如果我在多线程中使用扩展的 RTTI,我会遇到问题。

因此,我使用了 GetPropList,但这给了我所有属性的列表 - 不仅在当前 class 中发布(或明确说明)。

TBaseSettings = class(TPersistent)
published
    property Charset: string read FCharset write FCharset;
end;

TBasicSettings = class(TBaseSettings)
published
    property forums: Variant read fforums write fforums;
end;

TConcreteSettings = class(TBasicSettings)
published
    property forums; // <-- make it explicit visible: OK
    property prefix: Variant read fprefix write fprefix; // <-- OK
end;

我不想读取 字符集 属性。

我的第一个猜测是使用的修改版本来检查继承,但实际上forums 属性也被继承了。

也许 classic RTTI 无法做到这一点?我使用 Delphi 2010.

如果让您的代码以类似于调用 GetPropList 的方式调用 GetDeclaredPropList 很方便,请参阅下文。

编辑: 我重写了 Delphi 7 中的代码,我相信它也应该在 Delphi 2010 中工作(我不知道手边没有)。

type
  PPropData = ^TPropData;

function AfterString(P: Pointer): Pointer;
begin
  Result := Pointer(NativeUInt(P) + (PByte(P)^ + 1));
end;

function GetPropData(TypeData: PTypeData): PPropData;
begin
  Result := AfterString(@TypeData^.UnitName);
end;

function NextPropInfo(PropInfo: PPropInfo): PPropInfo;
begin
  Result := AfterString(@PropInfo^.Name);
end;

procedure GetDeclaredPropInfos(TypeInfo: PTypeInfo; PropList: PPropList);
var
  TypeData: PTypeData;
  PropData: PPropData;
  PropInfo: PPropInfo;
  I: Integer;
begin
  TypeData := GetTypeData(TypeInfo);
  PropData := GetPropData(TypeData);
  FillChar(PropList^, Sizeof(PPropInfo) * PropData^.PropCount, 0);
  PropInfo := PPropInfo(@PropData^.PropList);
  for I := 0 to PropData^.PropCount - 1 do
  begin
    PropList^[I] := PropInfo;
    PropInfo := NextPropInfo(PropInfo);
  end;
end;

function GetDeclaredPropList(TypeInfo: PTypeInfo; out PropList: PPropList): Integer; overload;
begin
  Result := GetPropData(GetTypeData(TypeInfo))^.PropCount;
  if Result > 0 then
  begin
    GetMem(PropList, Result * SizeOf(Pointer));
    GetDeclaredPropInfos(TypeInfo, PropList);
  end;
end;

function GetDeclaredPropList(AObject: TObject; out PropList: PPropList): Integer; overload;
begin
  Result := GetDeclaredPropList(PTypeInfo(AObject.ClassInfo), PropList);
end;

// example usage:
var
  I, Count: Integer;
  PropList: PPropList;
  PropInfo: PPropInfo;
begin
  Count := GetDeclaredPropList(TypeInfo(TConcreteSettings), PropList);
  try
    for I := 0 to Count - 1 do
    begin
      PropInfo := PropList^[I];
      Writeln(PropInfo^.Name);
    end;
  finally
    FreeMem(PropList);
  end;
end.
var
  TypeData: PTypeData;
  PropData: PPropData;
  PropInfo: PPropInfo;
  I: Integer;
begin
  TypeData := GetTypeData(TypeInfo(TConcreteSettings));
  PropData := GetPropData(TypeData);
  if Assigned(PropData) then
  begin
    PropInfo := @PropData^.PropList;
    for I := 0 to PropData^.PropCount - 1 do
    begin
      Writeln(PropInfo^.Name);
      PropInfo := NextPropInfo(PropInfo);
    end;
  end;
end;

关于 GetPropDataNextPropInfo 的实现,请参阅上面我的其他