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

lyb*_*rko 6 delphi delphi-7

我有这种记录类型

TDoublePoint = record
               X : Double;
               Y : Double;
               end;
Run Code Online (Sandbox Code Playgroud)

然后我有这个属性的对象

uses ..TypInfo;

TCell = class(TPersistent)
  private
    FZoom : TDoublePoint 
  published
    property Zoom : TDoublePoint read FZoom write FZoom;
end;
Run Code Online (Sandbox Code Playgroud)

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

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

.. ..

c := TCell.Create;
GetKind(c, 'Zoom');  //   <- error
c.Free;
Run Code Online (Sandbox Code Playgroud)

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

但为什么?有tkRecord在TTypeKind,所以我希望没有问题,读/写记录类型的属性,但现在看来,这是不可能的(?)谷歌搜索没有告诉太多.

Rem*_*eau 10

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

有一次,这是一个记录在案的限制:

已发布的属性仅限于某些数据类型.可以发布序数,字符串,类,接口,变体和方法指针类型.

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

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

RTTI问题在更高版本中得到修复(不确定哪一个.我猜测可能在Delphi 2010中,当扩展RTTI首次推出时).例如,您显示的代码在XE中按原样运行. GetPropInfo()可以Zoom按预期找到属性,而不必将任何编译器管理的类型引入TDoublePoint记录类型.