如何使用TypInfo单元

时间:2017-08-10 21:30:29

标签: delphi delphi-7

我有这种记录类型

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,所以我预计读/写记录类型的属性没有问题,但看起来,这是不可能的(?) 谷歌搜索并没有说太多。

1 个答案:

答案 0 :(得分:10)

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

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

  

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

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

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

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