【问题标题】:Get constant fields from a class using RTTI使用 RTTI 从类中获取常量字段
【发布时间】:2012-09-13 21:56:56
【问题描述】:

我可以从一个类中枚举常量(const)吗?

我试过了

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;

我想获得 c1、c2、c2。

这可能吗?

编辑: 我想要做的是为一些外部符号定义一些键(用于 cad 程序)

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

我不喜欢为此使用字段,因为我不喜欢将声明和初始化分开。 我不能使用枚举,因为我不能将值定义为字符串。

【问题讨论】:

  • 可能不会。可能在编译时不再有常量,而是立即值。单独保存它们没有什么意义
  • 如果你做了一个枚举,你可以将TypInfo 添加到你的uses 子句中,然后使用GetEnumNameGetEnumValue 在字符串和序数值之间进行转换。
  • 但是枚举值只能是整数,对吧?我需要字符串
  • GetEnumNameint 转换为stringGetEnumValuestring 转换为枚举 int。因此,即使枚举是一系列 ints,您也可以在代码中像字符串一样使用它们。
  • 我将添加一个示例作为答案,以便您了解如何将枚举转换为字符串并返回枚举...

标签: delphi rtti


【解决方案1】:

您无法通过 RTTI 获得这些常量。我怀疑您最好的解决方案是使用属性。这不仅对实际工作有好处,而且我认为这听起来像是解决您的问题的更清洁、更简单的解决方案。

【讨论】:

  • 属性到底是什么?它们应该包含什么?
  • 包含其键的每个类的属性。
【解决方案2】:

如果您使用枚举,您可以使用TypInfo 将字符串转换为枚举值,并将枚举值转换为代码中的字符串:

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;

(从我的脑海中输入 - 尚未测试过......)

这样 cad 程序可以将字符串传递给你的 Delphi 应用程序,你可以将它们翻译成枚举,或者你可以将枚举翻译成字符串传递给 cad 程序。执行case 语句也很容易,其中原始值是一个字符串,转换为一个枚举。由于 Delphi 不支持string case 语句,因此这非常方便。

【讨论】:

  • 在这种情况下,与类中的 var 字段相比,RTTI 是否会产生更多开销?枚举是否有一个通用的基本类型,所以我可以制定一个通用的方法来处理 symbol1 和 symbol2
  • 我从未分析过 RTTI 开销——但我通常使用它,以便我可以使用 case 语句并将字符串转换为枚举(参见上面的编辑)。我从来没有遇到过任何性能问题。
【解决方案3】:

我决定在我的课程中使用字段。由于我不想复制用于声明和初始化的字段,因此我使用 rtti 将字段初始化为字段的值。

好处是: 运行时没有 rtti 开销。 rtti 仅在应用启动期间执行。我还可以使用继承,这对我的项目非常有用。

【讨论】:

  • 很好。很高兴您有解决方案。但是,这不是您提出的问题的答案。请记住,您曾询问是否可以使用 RTTI 来获取类常量。
  • 关于您的问题的解决方案而不是您提出的问题的答案,您是否考虑过调用方法来检索这些字段名称?如果您有一个共同的祖先,这可能是一个虚拟类方法。否则它可能需要一个接口。
  • 我可能没有清楚地传达这一点,但我需要能够枚举并拥有像 key1.field1 这样的现成可用的密钥。我可以添加一个使用 rtti 的方法,但似乎是一个细节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-17
  • 1970-01-01
  • 2019-08-31
  • 1970-01-01
  • 2021-01-28
相关资源
最近更新 更多