获取属于任何类型的单元名称(TRttiType)

时间:2010-10-01 23:20:41

标签: delphi rtti delphi-xe

我需要获取任何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的单位名称吗?

2 个答案:

答案 0 :(得分:5)

看起来不像。 RTTI来自TTypeData结构,该结构仅具有为特定类型显式声明的UnitName字段。 (这比D2010和扩展的RTTI早。)你的#2看起来是获得它的最佳方式,并且可能是一个假设的TRTTIObject.UnitName如果要把它放入其中的话会如何计算它。

答案 1 :(得分:5)

信息存在,但解析合格名称是目前最好的方式。

如果你想通过以下方式做到这一点:

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

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中找到所有这些工作的示例是关键方法。此方法还显示QualifiedName始终包含UnitName。因此,您可以依赖原始的解析QualfiedName的方法。