3
votes

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.

3
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
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.
but enum value can only be integer right? I need string - Esben Skov Pedersen
GetEnumName translates the int to a string. GetEnumValue translates a string to the enum int. So even though an enum is a series of ints, you can use them in your code like strings. - James L.
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.

3 Answers

5
votes

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.

4
votes

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.

0
votes

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.