5

This code is not allowed:

class constructor TOmniMultiPipelineStage.Create;
var
  RTTIType: TRttiType;
begin
  RTTIType:= TRttiContext.GetType(self);
end;

[dcc32 Error] OtlParallel.pas(5040): E2003 Undeclared identifier: 'self'

The variant is also not allowed:

class constructor TOmniMultiPipelineStage.Create;
var
  RTTIType: TRttiType;
begin
  //Not really what I want because I want the actual type of the class
  //Not a fixed ancestor type 
  RTTIType:= TRttiContext.GetType(TOmniMultiPipelineStage);
end;

[dcc32 Error] OtlParallel.pas(5039): E2076 This form of method call only allowed for class methods or constructor

How do I get RTTI info on a class in its class constructor?

Note to self: loop over all descendants of a class: Delphi: At runtime find classes that descend from a given base class?

Community
  • 1
  • 1
Johan
  • 74,508
  • 24
  • 191
  • 319
  • possible duplicate of [Delphi use reflection in a class procedure for the getting dynamic class type](http://stackoverflow.com/questions/24559016/delphi-use-reflection-in-a-class-procedure-for-the-getting-dynamic-class-type) – Stefan Glienke Jul 16 '14 at 19:31
  • methods (and ctors) with class prefix are class members; they do not have a reference to the object, so there's no 'self' defined. – David Schwartz Jul 16 '14 at 19:47
  • 1
    @David Not so. Class methods have a Self. It is the meta class. Static class members have no Self. As it happens, class constructors are static, even though they don't have the static keyword. – David Heffernan Jul 16 '14 at 21:25
  • @david details here: http://docwiki.embarcadero.com/RADStudio/en/Methods#Ordinary_Class_Methods – David Heffernan Jul 16 '14 at 21:54

1 Answers1

3

Use the ClassInfo class method of TObject:

class constructor TMyClass.ClassCreate;
var
  ctx: TRttiContext;
  typ: TRttiType;
begin
  typ := ctx.GetType(ClassInfo);
end;

Note that I also fixed the syntax of your call to GetType, which is an instance method, and so must be called on an instance of TRttiContext.

A bigger problem for you is that class constructors are not going to be of use to you. A class constructor is static. They execute once only, for the type that defines them. They do not execute in the context of derived classes, as you are clearly expecting.

And likewise for class vars, which you discuss in the comments. There is but a single instance of a class var. You are expecting and hoping that there will be new instances for each derived class.

So whilst ClassInfo answers the question you asked, it won't be of any real use to you.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • A related question, if I subclass `TMyClass`, does the class constructor for TMyClass also kick in for the child with the correct typeinfo? – Johan Jul 16 '14 at 16:21
  • @Johan Class constructors are static and so you'd need to write a new class constructor for each subclass. The function in my answer executes exactly once in the lifetime of the module. – David Heffernan Jul 16 '14 at 16:31
  • 1
    Hmm, that would defeat the purpose of the exercise. I'll guess I'll have to move the RTTI query code to a normal constructor. But that would be wasteful, because the class var is then being set to the same value over and over. – Johan Jul 16 '14 at 16:33
  • I would query over all descendants of the object in this class constructor. – Johan Jul 16 '14 at 16:35
  • You can enumerate all types easily enough and take action for all types. You mention class vars. You'd need to redeclare the class var in all derived classes. There is a single instance of a class var, not one per class. – David Heffernan Jul 16 '14 at 16:37
  • @Johan Are you needing more help here? – David Heffernan Jul 17 '14 at 21:53
  • Thanks David, no I'm cool. I've moved the reflection code to a plain old constructor. It is a bit wasteful, but the constructors are not run in a tight loop (only once every few seconds) so it's OK. – Johan Jul 17 '14 at 23:05