获取属于任意类型的单元名称(TRttiType)
我需要获取任何 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
的单位名称?
I need to get the name of the unit (namespace) of any TRttiType
.
so far, I have tried the following.
1) using the PTypeData.UnitName
, this solution works, but only when the TTypeKind is 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) Parsing the QualifiedName
property, This solution works ok until now, but I'm not very happy with it.
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;
the question is, exist another reliable way to get the unit name of any TRttiType
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
信息就在那里,但解析限定名称是目前获取它的最佳方法。
如果您想以困难的方式做到这一点,您可以:
在 system.pas 单元中,您有一个变量 LibModuleList: PLibModule = nil; ,其中包含
已加载模块的列表。这是指向原始 RTTI 信息的指针,可以在没有 RTTI.pas 的情况下使用。您可以迭代所有原始信息来确定单位名称。
TLibModule 的关键值是:
使用
TypeInfo: PPackageTypeInfo;
您可以访问然后是 TypeTable,其中包含获取 PTypeInfo 的信息。
顺序。
可以在 Rtti.pas 中找到所有这些工作原理的示例,
TPackage.MakeTypeLookupTable
是关键方法。此方法还表明 QualifiedName 始终包含 UnitName。因此,可以依赖您解析 QualfiedName 的原始方法。The information is there but Parsing the Qualified Name is currently the best way to get to it.
If you want to do it the hard way you can by:
In the system.pas unit you have a variable
LibModuleList: PLibModule = nil;
that containsthe list of loaded modules. This is the pointer to the Raw RTTI Information that can be used without RTTI.pas. You could iterate all the raw information get determine the unit name.
The key values of the TLibModule are:
Using the
TypeInfo: PPackageTypeInfo;
you get access toThen there is TypeTable which contains the information to get to PTypeInfo.
sequence.
An example of how all this works can be found in Rtti.pas
TPackage.MakeTypeLookupTable
is the key method. This method also shows that QualifiedName always will contain the UnitName. As such your original method of parsing QualfiedName can be depended on.看起来好像没有。 RTTI 来自 TTypeData 结构,该结构仅具有为特定类型显式声明的 UnitName 字段。 (这早于 D2010 和扩展 RTTI。)您的#2 看起来是获得它的最佳方法,并且如果他们要放入一个假设的 TRTTIObject.UnitName,则可能是这样计算它的。
It doesn't look like there is. The RTTI comes out of the TTypeData structure, which only has a UnitName field explicitly declared for specific types. (This predates D2010 and extended RTTI.) Your #2 looks like the best way to get it, and is probably how a hypothetical TRTTIObject.UnitName would calculate it if they were to put one in.