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