6

我需要获取任何TRttiType.

到目前为止,我已经尝试了以下方法。

1) 使用PTypeData.UnitName,此解决方案有效,但仅当 TTypeKind 为 tkClass 时。

procedure ListAllUnits;
var
  ctx  : TRttiContext;
  lType: TRttiType;
  Units: TStrings;
begin
  Units:=TStringList.Create;
  try
    ctx := TRttiContext.Create;
    for lType in ctx.GetTypes do
     if lType.IsInstance then //only works for classes
      if Units.IndexOf(UTF8ToString(GetTypeData(lType.Handle).UnitName))<0 then
      Units.Add(UTF8ToString(GetTypeData(lType.Handle).UnitName));
  Writeln(Units.Text);
  finally
    Units.Free;
  end;
end;

2)解析QualifiedName属性,这个解决方案直到现在都可以正常工作,但我对它不是很满意。

procedure ListAllUnits2;

  function GetUnitName(lType: TRttiType): string;
  begin
    Result := StringReplace(lType.QualifiedName, '.' + lType.Name, '',[rfReplaceAll])
  end;

var
  ctx: TRttiContext;
  lType: TRttiType;
  Units: TStrings;
begin
  Units := TStringList.Create;
  try
    ctx := TRttiContext.Create;
    for lType in ctx.GetTypes do
      if Units.IndexOf(GetUnitName(lType)) < 0 then
        Units.Add(GetUnitName(lType));
    Writeln(Units.Text);
  finally
    Units.Free;
  end;
end;

问题是,是否存在另一种获取任何单位名称的可靠方法TRttiType

4

2 回答 2

5

好像没有。RTTI 来自 TTypeData 结构,它只有一个为特定类型显式声明的 UnitName 字段。(这早于 D2010 和扩展 RTTI。)您的 #2 看起来是获得它的最佳方式,并且可能是假设的 TRTTIObject.UnitName 将如何计算它,如果他们将其放入。

于 2010-10-01T23:24:01.263 回答
5

信息在那里,但解析限定名称是目前获得它的最佳方式。

如果您想以艰难的方式做到这一点,可以通过:

在 system.pas 单元中,您有一个LibModuleList: PLibModule = nil;包含已加载模块列表的变量。这是指向可以在没有 RTTI.pas 的情况下使用的原始 RTTI 信息的指针。您可以迭代所有原始信息来确定单位名称。

TLibModule 的关键值是:

  PLibModule = ^TLibModule;
  TLibModule = record
    Next: PLibModule;  { Linked List of Loaded Modules)
    Instance: LongWord;
    ...
    TypeInfo: PPackageTypeInfo; { List of contained Package Information }
    ...
  end;

使用TypeInfo: PPackageTypeInfo;您可以访问

  PPackageTypeInfo = ^TPackageTypeInfo;
  TPackageTypeInfo = record
    TypeCount: Integer;
    TypeTable: PTypeTable;
    UnitCount: Integer;
    UnitNames: PShortString; { concatenation of Pascal strings, 
                               one for each unit }
  end;

然后是 TypeTable,其中包含获取 PTypeInfo 的信息。
顺序。

  TTypeTable = array[0..MaxInt div SizeOf(Pointer) - 1] of Pointer;
  PTypeTable = ^TTypeTable;

可以在 Rtti.pas 中找到所有这些工作原理的示例,TPackage.MakeTypeLookupTable即 key 方法。此方法还表明 QualifiedName 将始终包含 UnitName。因此,您可以依赖于解析 QualfiedName 的原始方法。

于 2010-10-02T15:53:14.197 回答