0

I'm trying to list my interfaces and classes to build a framework, but the GetTypes () method doesn't find my types, what do I have to change in my source to make it possible?

unit untPrincipal;

interface

uses
   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Rtti, Vcl.StdCtrls, System.TypInfo;

type
   TForm1 = class(TForm)
      btnTeste: TButton;
      mmoSaida: TMemo;
      procedure btnTesteClick(Sender: TObject);
   private
      { Private declarations }
   public
      { Public declarations }
   end;

   IMyInterface = interface(IInterface)
      ['{60B148AA-0750-432F-8AC0-1423707803AC}']
      procedure Fazer;
   end;

   IMyInterface2 = interface(IInvokable)
      ['{80A5566A-D8A4-44A7-AEC6-7874F95EFA13}']
      procedure Fazer;
   end;

{$M+}

   IMyInterface3 = interface
      ['{7A6ED55C-2A96-4BCF-ADD1-65159B37F258}']
      procedure Fazer;
   end;
{$M-}

   TMyClass = class(TInterfacedObject, IMyInterface)
   public
      procedure Fazer;
   end;

   TMyClass2 = class(TInterfacedObject, IMyInterface2)
   public
      procedure Fazer;
   end;

   TMyClass3 = class(TInterfacedObject, IMyInterface3)
   public
      procedure Fazer;
   end;

var
   Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.btnTesteClick(Sender: TObject);
var
   ctx: TRttiContext;
   ctypes: TArray<TRttiType>;
   ctype: TRttiType;
begin
   mmoSaida.Clear;
   ctx := TRttiContext.Create;
   try
      ctypes := ctx.GetTypes();
      for ctype in ctypes do
      begin
         mmoSaida.Lines.Add(ctype.ToString)
      end;
   finally
      ctx.Free;
   end;
end;

{ TMyClass }

procedure TMyClass.Fazer;
begin
   ShowMessage('procedure TMyClass.Fazer;');
end;

{ TMyClass2 }

procedure TMyClass2.Fazer;
begin
   ShowMessage('procedure TMyClass2.Fazer;');
end;

{ TMyClass3 }

procedure TMyClass3.Fazer;
begin
   ShowMessage('procedure TMyClass3.Fazer;');
end;

end.

The code above lists several types, including TForm1 and other simple types. but it does not list neither my interfaces nor my classes.

Delphi 10.3 Update 1 (Version 26.0.33219.4899)

Thank you

Passella
  • 640
  • 1
  • 8
  • 23
  • 7
    since you are not using/creating any of the types, they wont be included in the runtime, hence RTTI does not find them – whosrdaddy Aug 13 '19 at 15:37
  • 1
    There are techniques to [prevent linker from eliminating some symbols](https://stackoverflow.com/questions/1606105/how-do-i-force-the-linker-to-include-a-function-i-need-during-debugging). – Peter Wolf Aug 13 '19 at 21:41
  • @PeterWolf My problem is that I pass an interface to a constructor function and it scans the system behind classes with my attribute, once found, the function builds the given object, the function already works if I reference that class somewhere, But I don't want to do that. – Passella Aug 14 '19 at 14:08
  • @whosrdaddy This solves my problem by just referencing my class at some point, such as: TMyClass.ClassName (); in any part of my code, but it would make sense that I have to reference the class in any part of my code, I understand that as it "does not use" the class, it is not listed in RTTI by the GetTypes () method. but for better use of the framework, the idea was not to have to reference the class. – Passella Aug 14 '19 at 14:15

1 Answers1

1

You are required to register the type in some way (like a factory concept). With a normal class factory you add classes to the factory class list. The same way applies to RTTI, only then it’s automatically added when you ‘use’ the class.

But in both casus you don’ t want the routine/unit using the class factory to have a link to the actual units containing the classes (loose copeling).

So to make this work, you can add the ‘TMyClass.Classname’ to the ‘initialization’ section of the unit in which ‘TMyClass’ is defined. Then Rtti will know it. This way there’s no need to ‘use’ the class in the main unit of your application.

R. Hoek
  • 916
  • 8
  • 27