2010-10-01 14 views
6

我需要獲取任何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

回答

5

它看起來並不像。 RTTI來自TTypeData結構,它只有一個爲特定類型顯式聲明的UnitName字段。 (這在D2010和擴展RTTI之前。)#2看起來是獲取它的最佳方式,並且可能是假設的TRTTIObject.UnitName如果要將其放入,它將如何計算它。

5

信息在那裏但解析合格的名稱是目前最好的解決方法。

如果你想這樣做,通過艱辛的道路,您可以:

在system.pas單位你有一個變量LibModuleList: PLibModule = nil;包含 加載模塊的列表。這是指向Raw 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的原始方法。