1

My question is how to access a class which is in an other unit? For an example:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes,
  System,
  StrUtils,
  Math,
  TypInfo,
  Data in 'Data.pas';

var
  Str, name, value                      : string;
  List, tmpList                         : TStringList;
  i                                     : Integer;
  Obj                                   : TObject;
  CRef                                  : TPersistentClass;
  d                                     : TData;
begin
  d := TData(GetClass('Data.TData').Create);
  Writeln(Format('%s', [d.Name]));
  Readln;
  Readln;
end.

And the Data unit :

unit Data;

interface
 uses
  SysUtils,
  Classes;
type
  TData = class(TObject)
    FName : string;
  published
    property Name : string read FName write FName;
  end;
type
  TIn = class(TObject)
    FName : string;
  published
    property Name : string read FName write FName;
  end;
implementation

end.

The problem is that the method GetClass return me always nil. I know that there is a questions like this one but they doesn't helped me.

Thanks in advance!

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Jordan Borisov
  • 1,603
  • 6
  • 34
  • 69

4 Answers4

5

Given that d is defined as TData, can't you simply use d := TData.Create()?

Anyway if you want to create class from its name, you have to (look this link) call RegisterClass before using GetClass or that class won't be recognized and you get a nil.

Community
  • 1
  • 1
Marco
  • 56,740
  • 14
  • 129
  • 152
  • Yes I can but the problem is that I must create an instance from the name of the class in string. – Jordan Borisov Oct 12 '11 at 09:30
  • Yes I have to use the RegisterClass method but for the class I have only the name of it in string. How can I register class if I have only the name in string? – Jordan Borisov Oct 12 '11 at 09:35
  • @Jordan Borisov: David Heffernan and ain answered your last question, take a look – Marco Oct 12 '11 at 09:39
  • @Jordan Borisov: don't you have the source code for TData class? Or your is just an example and you want to create any class user gives you by name? – Marco Oct 12 '11 at 09:42
  • Yes any class which is created and I want to create an instance of it only by it's name in string type. In Java this is called Reflection. – Jordan Borisov Oct 12 '11 at 09:43
  • 1
    @Jordan Borisov: ok, but if you have to access _any_ class, then what you can do with taht class? Beeing generic you don't know its properties and methods... if you don't get it using RTTI... so, what's the main goal of this? – Marco Oct 12 '11 at 09:46
  • @Jordan In Delphi it is called RTTI. What version of Delphi do you have? – David Heffernan Oct 12 '11 at 09:46
  • @Jordan: as I've already told you (David and Ville are completely right) you should use RTTI but you're facing a great job to be complete and efficient I think... – Marco Oct 12 '11 at 09:48
5

If you are using one of the later Delphi versions you can use the RTTI unit.

uses RTTI;
..
  var
    R : TRttiContext;
  begin
    R.FindType('Data.TData')
...

In your example TIn is not a inner class, but inner classes can also be accessed like this:

R.FindType('Data.TData.TIn')
Ville Krumlinde
  • 7,021
  • 1
  • 33
  • 41
4

You didn't register the class. You need to call RegisterClass.

How can I register class if I have only the name in string?

Typically you would place a call to RegisterClass in the initialization section unit that declares the class.

When you come to call RegisterClass you will discover that the class needs to derived from TPersistent:

procedure RegisterClass(AClass: TPersistentClass);
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
2

Please read the GetClass documentation. It only works with registered persistent classes. So The first thing you must change in order to use it is descend from TPersistent, ie

type
  TData = class(TPersistent)
    FName : string;
  published
    property Name : string read FName write FName;
  end;

and then you have to make sure that the class is registred, ie you have to call RegisterClasses, perhaps in the initialization section of the unit

initialization
  RegisterClasses([TData]);
ain
  • 22,394
  • 3
  • 54
  • 74