6

任意のユニット (名前空間) の名前を取得する必要があります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どうかです。

4

2 に答える 2

5

情報はそこにありますが、修飾名を解析することが現時点で最良の方法です。

難しい方法でやりたい場合は、次の方法で実行できます。

system.pas ユニットにはLibModuleList: PLibModule = nil;、読み込まれたモジュールのリストを含む変数があります。これは、RTTI.pas なしで使用できる生の RTTI 情報へのポインターです。すべての生の情報を繰り返し取得して、ユニット名を決定できます。

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;

次に、PTypeInfo を取得するための情報を含む TypeTable があります。
順序。

  TTypeTable = array[0..MaxInt div SizeOf(Pointer) - 1] of Pointer;
  PTypeTable = ^TTypeTable;

Rtti.pas でこれらすべてがどのように機能するかの例TPackage.MakeTypeLookupTableは、重要なメソッドです。このメソッドは、QualifiedName が常に UnitName を含むことも示しています。そのため、QualfiedName を解析する元の方法に依存する可能性があります。

于 2010-10-02T15:53:14.197 に答える
5

あるようには見えません。RTTI は、特定の型に対して明示的に宣言された UnitName フィールドのみを持つ TTypeData 構造体から取得されます。(これは D2010 および拡張 RTTI よりも前の日付です。) あなたの #2 は、それを取得するための最良の方法のように見えます。

于 2010-10-01T23:24:01.263 に答える