如何使用Delphi RTTI来获取和设置记录值 [英] How to use Delphi RTTI to get and set Record Values

查看:403
本文介绍了如何使用Delphi RTTI来获取和设置记录值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Delphi XE或更高版本中使用增强的RTTI功能来读取和写入对象到XML。到目前为止,我已经成功地使用整数,浮点数,字符串,枚举类型,集合和类,但无法正确输出或读取记录。问题似乎是获取一个实例(指针)到record属性。

I'm attempting to use the enhanced RTTI features in Delphi XE or later, to read and write objects to XML. So far I've been successful with integers, floats, strings, enumerated types, sets and classes but can't output or read records correctly. The problem seems to be getting an instance (pointer) to the record property.

//Outputs Properties To XML
procedure TMyBase.SaveToXML(node: TJclSimpleXMLElem);
var
  child , subchild : TjclSimpleXMLElem ;
  FContext : TRttiContext ;
  FType    : TRttiType ;
  FProp    : TRttiProperty ;
  Value    : TValue ;
  MyObj    : TMyBase ;
  FField   : TRttiField ;
  FRecord  : TRttiRecordType ;
  Data     : TValue ;
begin
  FContext := TRttiContext.Create ;
  FType := FContext.GetType ( self.ClassType ) ;
  Child := node.Items.Add ( ClassName ) ;
  for FProp in FType.GetProperties do begin
    if FProp.IsWritable then begin
      case FProp.PropertyType.TypeKind of
        tkClass : begin
          MyObj := TMyBase ( FProp.GetValue ( self ).AsObject ) ;
          MyObj.SaveClass ( Child.Items.Add ( FProp.Name ) , FContext ) ;
          end ;
        tkRecord : begin
          subchild := Child.Items.Add ( FProp.Name ) ;
          FRecord := FContext.GetType(FProp.GetValue(self).TypeInfo).AsRecord ;
          for FField in FRecord.GetFields do begin
            >>> self is not the correct instance <<<
            Value := FField.GetValue ( self ) ;
            subchild.Items.Add ( FField.Name ).Value := Value.ToString ;
            end;
          end ;
        else begin
          Value := FProp.GetValue(self) ;
          Child.Items.Add ( FProp.Name ).Value := Value.ToString ;
          end;
        end;
      end ;
    end ;
  FContext.Free ;
end;

我怀疑如果我能弄清楚如何获取值,那么设置它们不应该是问题。然后到数组,哦,男孩!

I suspect that if I can figure out how to get the values then setting them shouldn't be a problem. Then onto arrays, oh boy!

更新:请参阅以下。 (作为单独的答案迁移以提高可见性)。

Updates: Please see below. (Migrated as separate answer to improve visibility).

推荐答案

我假定您正在尝试保存记录类型字段的值的自我运行时类型,是吗?

I presume you are trying to save the value of a record-typed field of the runtime type of Self, yes?

您必须首先获取该字段的值,使用 FProp.GetValue(Self) code>。假设你把它放在一个名为 FieldValue 的类型为$ code> TValue 的变量中。然后,您可以随意保存记录值的字段,尽管您可能希望为其编写递归过程,因为记录的字段本身可能是字段。用于记录的字段getter希望记录的地址(指向其开始的指针)与setter对称;设定者期望地址而不是值,因为否则将不会有简单的方法来修改另一个类或记录中的原位字段,因为记录以其他方式传递价值。

You have to get the value of the field first, with FProp.GetValue(Self). Let's say you put that in a variable called FieldValue of type TValue. You can then save the fields of the record value as you wish, though you'll probably want to write a recursive procedure for it, as the fields of the record may themselves be fields. The field getter for records expects the address of the record (a pointer to its start) for symmetry with the setter; the setter expects the address rather than the value because otherwise there would be no easy way to modify a field "in situ" in another class or record, since records are otherwise passed around by value.

您可以通过 FieldValue.GetReferenceToRawData 获得该值,该值将返回指向 TValue code>。

You could get that with FieldValue.GetReferenceToRawData, which will return a pointer to the start of the records stored inside the TValue.

希望这能给你足够的线索继续。

Hopefully this gives you enough clues to continue.

这篇关于如何使用Delphi RTTI来获取和设置记录值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆