4
  1. I want to get the whole list of classes defined in a specific unit
  2. How can I get the list of all instances of those classes, irrespective of where they are created?
LU RD
  • 34,438
  • 5
  • 88
  • 296
Vibeeshan Mahadeva
  • 7,147
  • 8
  • 52
  • 102

2 Answers2

5

First before to answer your question, remember always include your delphi version in questions related to the Rtti.

1) Asumming which you are using a new version of delphi (>=2010) you can get the unit name of a type using the QualifiedName property , from there you must check the IsInstance property to determine if is a class.

Check the next sample.

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Rtti,
  System.SysUtils;

procedure Test;
Var
 t : TRttiType;
  //extract the unit name from the  QualifiedName property
  function GetUnitName(lType: TRttiType): string;
  begin
    Result := StringReplace(lType.QualifiedName, '.' + lType.Name, '',[rfReplaceAll])
  end;

begin
 //list all the types of the System.SysUtils unit
  for t in TRttiContext.Create.GetTypes do
   if SameText('System.SysUtils',GetUnitName(t)) and (t.IsInstance) then
     Writeln(t.Name);
end;

begin
  try
    Test;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

2) The Rtti can't list the instances of the classes. because the Rtti is about type information and not of instances.

RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • 1
    What about DeclaringUnitName? Is it Ok to use that? – David Heffernan Jan 25 '12 at 14:33
  • Yeah this will work too, unfortunally the `DeclaringUnitName` is part of specific rtti types, but in this case for instances is ok. In the answer I recommend parse the `QualifiedName` to get the unit name because in the past I found some cases where the unit name is not present in some types check ths question for more info [Getting the Unit Name wich belongs to any type (TRttiType)](http://stackoverflow.com/questions/3843628/getting-the-unit-name-wich-belongs-to-any-type-trttitype) – RRUZ Jan 25 '12 at 14:40
  • Thanks a lot. Oh, one more Q while I have your ear. Are `IsInstance` and `AsInstance` the idiomatic ways to do this as opposed to `is` or `as` operators? – David Heffernan Jan 25 '12 at 14:45
  • @DavidHeffernan `AsInstance` try to cast the type to `TRttiInstanceType` so will fail to types which not are instances (classes). – RRUZ Jan 25 '12 at 14:47
  • I read that other question now. It looks like the issue it refers to is when trying to find the unit name for any variety of `TRttiType`. But for an instance, and you are writing `IsInstance`, surely it's simpler and cleaner to use `DeclaringUnitName`? – David Heffernan Jan 25 '12 at 15:12
  • @DavidHeffernan , yes is much more cleaner use `DeclaringUnitName` and in this case works. In my answer I give a more general solution based on my experience because in the past I have issues resolving the unit name of some types. – RRUZ Jan 25 '12 at 15:15
  • OK, all clear now. I think that point would be better off in the answer than the comments. If you did that I'd be happy to delete all the comments and tidy up. – David Heffernan Jan 25 '12 at 15:17
3

Question 1

The following code does what you ask, relying on the new RTTI introduced in Delphi 2010:

program FindClassesDeclaredInUnit;

{$APPTYPE CONSOLE}

uses
  SysUtils, Rtti, MyTestUnit in 'MyTestUnit.pas';

procedure ListClassesDeclaredInNamedUnit(const UnitName: string);
var
  Context: TRttiContext;
  t: TRttiType;
  DeclaringUnitName: string;
begin
  Context := TRttiContext.Create;
  for t in Context.GetTypes do
    if t.IsInstance then
    begin
      DeclaringUnitName := t.AsInstance.DeclaringUnitName;
      if SameText(DeclaringUnitName, UnitName) then
        Writeln(t.ToString, ' ', DeclaringUnitName);
    end;
end;

begin
  ListClassesDeclaredInNamedUnit('MyTestUnit');
  Readln;
end.


unit MyTestUnit;

interface

type
  TClass1 = class
  end;

  TClass2 = class
  end;

implementation

procedure StopLinkerStrippingTheseClasses;
begin
  TClass1.Create.Free;
  TClass2.Create.Free;
end;

initialization
  StopLinkerStrippingTheseClasses;

end.

Question 2

There is no global registry of object instances.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490