如何使用 TypInfo 单元获取 'record' 类型的 属性

How to get property of the 'record' type using TypInfo unit

我有这个记录类型

TDoublePoint = record
               X : Double;
               Y : Double;
               end;

那我反对这个属性

uses ..TypInfo;

TCell = class(TPersistent)
  private
    FZoom : TDoublePoint 
  published
    property Zoom : TDoublePoint read FZoom write FZoom;
end;

但是当我想用这个函数得到这个 属性 的 PropInfo 时:

function GetKind(AObject:TObject; Propertyname :shortstring):TTypeKind;
var p :ppropinfo;
begin
  p:=GetPropInfo(AObject, Propertyname);  // <p = nil
  Result:= p^.proptype^.Kind;
end;

.. ..

c := TCell.Create;
GetKind(c, 'Zoom');  //   <- error
c.Free;

我得到错误,因为变量 p 在函数中是 nil

但是为什么呢? TTypeKind中有tkRecord,所以我预计记录类型的read/write和属性没有问题,但似乎不可能(?) Google 搜索结果不多。

Delphi 7 默认不为记录类型生成 RTTI,因此使用记录类型的 published 属性 也不会有 RTTI(您可以使用TypInfo.GetPropList() 确认)。

在某一时刻,这是记录在案的限制:

Published properties are restricted to certain data types. Ordinal, string, class, interface, variant, and method-pointer types can be published.

但是,有一个解决方法。 如果 记录类型包含任何编译器管理的数据类型(长字符串、接口、动态数组等),那么将为该记录类型生成 RTTI,任何 published 属性 使用该记录类型,因此 GetPropInfo() 可以找到此类属性(我已经确认这在 Delphi 7 中有效)。

您的 TDoublePoint 记录不包含任何编译器管理的数据类型,所以这就是 GetPropInfo() 为您的 TCell.Zoom 属性.[=21 返回 nil 的原因=]

该 RTTI 问题已在更高版本中修复(不确定是哪个版本。我猜可能是在 Delphi 2010 年首次引入扩展 RTTI 时)。例如,您展示的代码在 XE 中对我有效。 GetPropInfo() 可以按预期找到 Zoom 属性,而无需将任何编译器管理的类型引入 TDoublePoint 记录类型。