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