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

RRU*_*RUZ 6 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;
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

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

Mas*_*ler 5

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


Rob*_*ove 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;
Run Code Online (Sandbox Code Playgroud)

使用TypeInfo: PPackageTypeInfo;您可以访问

  PPackageTypeInfo = ^TPackageTypeInfo;
  TPackageTypeInfo = record
    TypeCount: Integer;
    TypeTable: PTypeTable;
    UnitCount: Integer;
    UnitNames: PShortString; { concatenation of Pascal strings, 
                               one for each unit }
  end;
Run Code Online (Sandbox Code Playgroud)

然后是TypeTable,其中包含要访问PTypeInfo的信息.
序列.

  TTypeTable = array[0..MaxInt div SizeOf(Pointer) - 1] of Pointer;
  PTypeTable = ^TTypeTable;
Run Code Online (Sandbox Code Playgroud)

在Rtti.pas中可以找到所有这些工作原理的一个例子TPackage.MakeTypeLookupTable是关键方法.此方法还显示QualifiedName始终包含UnitName.因此,可以依赖于原始的解析QualfiedName的方法.