3

Can I enumerate the constants(const) from a class?

I have tried

MyClass = class
const
  c1 = 'c1';
  c2 = 'c2';
  c3 = 'c3';
end;

procedure GetConst();
var
  ctx: TRttiContext;
  objType: TRttiType;
  field: trttifield;
  s: string;
begin
  ctx := TRttiContext.Create;
  objType := ctx.GetType(MyClass.ClassInfo);
  for field in objType.GetDeclaredFields do
    s:= field.Name;
end;

I would like to get c1, c2, c2.

Is this possible?

edit: what I want to do is define some keys for some external symbols(for a cad program)

symbol1=class
    const
    datafield1='datafield1';
    datafield2='datafield2';
end;
symbol2=class
    const
    datafield21='datafield21abc';
    datafield22='datafield22abc';
end

I don't like to use fields for this because I prefer not to seperate declareration and initialization. I can't use an enum since I can't define the value as a string.

Esben Skov Pedersen
  • 4,437
  • 2
  • 32
  • 46
  • 1
    probably not. Probably at compile time there are no more constants but the immediate values instead. there is little sense to kkep them separately – Arioch 'The Sep 21 '12 at 13:31
  • If you did an enum, you could add `TypInfo` to your `uses` clause and then use `GetEnumName` and `GetEnumValue` to translate between the string and ordinal values. – James L. Sep 21 '12 at 13:55
  • but enum value can only be integer right? I need string – Esben Skov Pedersen Sep 21 '12 at 13:56
  • `GetEnumName` translates the `int` to a `string`. `GetEnumValue` translates a `string` to the enum `int`. So even though an enum is a series of `int`s, you can use them in your code like strings. – James L. Sep 21 '12 at 15:41
  • I'll add an example as an answer so you see how to translate an enum to a string and back to an enum... – James L. Sep 21 '12 at 15:48

3 Answers3

5

You can't get at those constants through RTTI. I suspect your best solution will be to use attributes instead. Not only will that have the benefit of actually working, I think it sounds like a cleaner and simpler solution to your problem.

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

If you use an enum, you can use TypInfo to translate strings to the enum values, and the enum values to strings in your code:

type
  TDataFieldName = (datafield1, datafield2, datafield3);

uses TypInfo;

var df: TDataFieldName;
begin
  df := TDataFieldName(GetEnumValue(TypeInfo(TDataFieldName), 'datafield1'));

  ShowMessage(GetEnumName(TypeInfo(TDataFieldName), Ord(df)));

  case df of
    datafield1:;
    datafield2:;
    datafield3:;
  end;
end;

(Typed from my head -- haven't tested this...)

This way the cad program can pass strings to your Delphi app, and you can translate them to the enum, or you can translate the enum to a string to pass to the cad program. It's also easy to do a case statement where the original value was a string, converted to an enum. This has come in very handy since Delphi doesn't support string case statements.

James L.
  • 9,384
  • 5
  • 38
  • 77
  • Does RTTI impose much overhead in this situation as compared to say var fields in a class? Is there a common base type for enums so I can make a common method to handle symbol1 and symbol2 – Esben Skov Pedersen Sep 22 '12 at 10:14
  • I've never analyzed the RTTI overhead -- but I commonly use this so that I can use a `case` statement with the string converted to an enum (see edit above). I've never had any performance issues. – James L. Sep 22 '12 at 15:52
0

I've decided to use fields in my classes. Since I don't want to duplicate fields for declaration and initialization, i'm using rtti to initialize fields to the value of the field.

The benefits are: No rtti overhead on runtime. rtti is only performed during app startup. Also I get to use inheritance which is very useful for my project.

Esben Skov Pedersen
  • 4,437
  • 2
  • 32
  • 46
  • That's nice. Glad that you have a solution. However, this is not an answer to the question that you asked. Remember that you asked if RTTI could be used to obtain class constants. – David Heffernan Sep 23 '12 at 06:13
  • Regarding solutions to your problem as opposed to answers to the question you asked, did you consider a method call to retrieve these field names? This would likely be a virtual class method if you have a common ancestor. Otherwise it would probably need to be an interface. – David Heffernan Sep 23 '12 at 06:53
  • I may not have communicated this clearly, but I need to be able to enumerate and have keys readily available like key1.field1. I could add a method to use rtti, but seems like a detail. – Esben Skov Pedersen Sep 23 '12 at 08:31