使用RTTI从tkSet类型中获取可能的值并显示它们

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用RTTI从tkSet类型中获取可能的值并显示它们相关的知识,希望对你有一定的参考价值。

有人可能已经问过这个问题了,但还没找到,所以问题出在这里:

我想解析一个组件的tkSet属性(在我们的例子中是Panel1),但我不知道如何正确地做到这一点。我能够使用rContext.FindType()找到集合的基本枚举类型,但我几乎可以肯定有一些更优雅/简单的方法来做到这一点。从那时起,我完全迷失了。我应该通过枚举类型的值,并根据compoenent的当前属性值检查每个值。

procedure TForm12.GetProperties2;
var
  rContext: TRttiContext;
  rType: TRttiType;
  rProp: TRttiProperty;
begin
  rType := rContext.GetType(Panel1.ClassType);

  for rProp in rType.GetProperties do
  begin
    if (rProp.Visibility in [mvPublished]) and (rProp.PropertyType.TypeKind in [tkSet]) and (rProp.Name = 'Anchors') then
    begin
      Memo1.Lines.Add('Name: ' + rProp.Name);
      Memo1.Lines.Add('PropertyType: ' + rProp.PropertyType.ToString);
      Memo1.Lines.Add('Value: ' + rProp.GetValue(Panel1).ToString);
      Memo1.Lines.Add('QualifiedName: ' + rProp.PropertyType.QualifiedName);
      Memo1.Lines.Add('ElementType: ' + rContext.FindType(rProp.PropertyType.QualifiedName).AsSet.ElementType.ToString);
      // here comes the desired results
      Memo1.Lines.Add('Possible values:');
      Memo1.Lines.Add(' 0 > akLeft');
      Memo1.Lines.Add(' 1 > akTop');
      Memo1.Lines.Add(' 2 > akRight');
      Memo1.Lines.Add(' 3 > akBottom');
      Memo1.Lines.Add('Present values:');
      Memo1.Lines.Add(' 0 > akLeft');
      Memo1.Lines.Add(' 1 > akTop');
      Memo1.Lines.Add('');
    end;
  end;
end;

另一个可能的问题是没有基本枚举类型的set属性,例如,如果您查看TPanel.StyleElements属性,您可以看到TStyleElements的声明如下:

TStyleElements = set of (seFont, seClient, seBorder);

在这种情况下,ElementType无法正常工作。

所以问题是如何解析tkSet类型属性以使用RTTI上下文获得所需的结果?

答案

使用基本的TypInfo非常简单。

procedure PrintSet(const v: TValue); // v contains a value from a set type
var
  enumType: PTypeInfo;
  enumData: PTypeData;
  buffer: set of Byte; // biggest possible set type
  i: Integer;
begin
  buffer := [];
  v.ExtractRawData(@buffer);
  enumType := v.TypeInfo.TypeData.CompType^;
  enumData := enumType.TypeData;
  for i := enumData.MinValue to enumData.MaxValue do
    Writeln(GetEnumName(enumType, i) + ' = ' + (i in buffer).ToString(TUseBoolStrs.True));
end;

set of Byte是可能的最大集合类型,因此我们可以将其用作缓冲区,其中所有内容都适合,然后使用TValue.ExtractRawData方法将实际集合类型中的数据写入其中。通过将其设置为空之前,其他所有内容都归零。

然后我们可以使用枚举类型的类型数据来获取最小值和最大值。由于非连续的枚举类型没有typeinfo,我们不需要处理它,实际上只处理与经典位掩码二进制兼容的那些。

以上是关于使用RTTI从tkSet类型中获取可能的值并显示它们的主要内容,如果未能解决你的问题,请参考以下文章

SQL 如何获取 XML 数据列的值并在 where 子句中使用它

从输入中获取值并在 div 中显示

如何获取csv文本的值并插入访问

如何从对象类型中动态获取值并在扩展面板角材料中实现?

Bash - 获取命令(字符串)的值并查看它是不是与另一个字符串匹配

怎样从对象中获取键值并保存在对象中