发布时间 : 星期五 文章Delphi 的RTTI机制浅探更新完毕开始阅读7f38b9c689eb172ded63b711
tkInteger, tkChar, tkWChar: (); tkEnumeration: (
BaseType: PPTypeInfo; // 指针的指针,它指向枚举的 PTypeInfo NameList: ShortStringBase; // 枚举的名称字符串(不能直接取用) EnumUnitName: ShortStringBase));//所在的单元名称(不能直接取用) tkSet: ( CompType: PPTypeInfo));// 指向集合基类 RTTI 指针的指针 end;
下面是一个获取有序类型和集合类型的 RTTI 信息的函数:
procedure GetOrdTypeInfo(ATypeInfo: PTypeInfo; AStrings: TStrings); var
OrdTypeData: PTypeData; I: Integer; begin
OrdTypeData := GetTypeData(ATypeInfo);
AStrings.Add('------------------------------------'); AStrings.Add('Type Name: ' + ATypeInfo^.Name);
AStrings.Add('Type Kind: ' + GetEnumName(TypeInfo(TTypeKind), Integer(ATypeInfo^.Kind)));
AStrings.Add('Data Type: ' + GetEnumName(TypeInfo(TOrdType), Integer(OrdTypeData^.OrdType)));
if ATypeInfo^.Kind <> tkSet then begin
AStrings.Add('Min Value: ' + IntToStr(OrdTypeData^.MinValue)); AStrings.Add('Max Value: ' + IntToStr(OrdTypeData^.MaxValue)); end;
if ATypeInfo^.Kind = tkSet then
GetOrdTypeInfo(OrdTypeData^.CompType^, AStrings); if ATypeInfo^.Kind = tkEnumeration then
for I := OrdTypeData^.MinValue to OrdTypeData^.MaxValue do
AStrings.Add(Format(' Value %d: %s', [I, GetEnumName(ATypeInfo, I)])); end;
在表单上放置一个 TListBox,运行以下代码查看结果:
type TMyEnum = (EnumA, EnumB, EnumC);
procedure TForm1.FormCreate(Sender: TObject); begin
GetOrdTypeInfo(TypeInfo(Char), ListBox1.Items); GetOrdTypeInfo(TypeInfo(Integer), ListBox1.Items);
GetOrdTypeInfo(TypeInfo(TFormBorderStyle), ListBox1.Items); GetOrdTypeInfo(TypeInfo(TBorderIcons), ListBox1.Items); GetOrdTypeInfo(TypeInfo(TMyEnum), ListBox1.Items); end;
(如果枚举元素没有按缺省的 0 基准定义,那么将不能产生 RTTI 信息,为什么?)
9
⊙ 获取其它数据类型的 RTTI 信息
上面讨论了几个典型的 RTTI 信息的运行,其它的数据类型的 RTTI 信息的获取方法与上面类似。由于这些操作更加简单,就不一一讨论。下面概述其它类型的 RTTI 信息的情况:
LongString、WideString 和 Variant 没有 RTTI 信息; ShortString 只有 MaxLength 信息;
浮点数类型只有 FloatType: TFloatType 信息;
TFloatType = (ftSingle, ftDouble, ftExtended, ftComp, ftCurr); Int64 只有最大值和最小值信息(也是 64 位整数表示); Interface 和动态数组不太熟悉,就不作介绍了。
⊙ 结束
来自:小雨哥, 时间:2004-1-21 13:23:00, ID:2420817 他们说,执行下面代码看看: implementation uses Unit2; {$R *.DFM}
procedure TForm1.btnShowClick(Sender: TObject); begin
if FindClass('TForm2') <> nil then ShowMessage('有了 :)'); end;
procedure TForm1.btnRegisterClick(Sender: TObject); begin
RegisterClass(TForm2); end;
先不要按 btnRegister 这个按钮,直接按 btnShow 发现提示错误。
来自:savetime, 时间:2004-1-21 15:37:00, ID:2420892 to 小雨歌,
你说的是问题还是提醒我 FindClass 也属于 RTTI ?
本文中的 RTTI 是最简单的,我准备在续文写下更详细的 RTTI 内容。
来自:savetime, 时间:2004-1-23 1:23:00, ID:2421471 大家新年好,《Delphi 的RTTI机制浅探(续)》 写完了,敬请指正: http://www.delphibbs.com/delphibbs/dispq.asp?lid=2421470
来自:beta, 时间:2004-1-27 18:28:00, ID:2423886 希望把您写的几篇笔记转贴到 www.01cn.net 还望恩准[:D]
你要是不说 no 我就当答应了啊[:D]
10
Delphi 的RTTI机制浅探(续)
savetime2k@yahoo.com 2004.1.22 http://savetime.delphibbs.com
本文是《Delphi 的RTTI机制浅探》的续篇,上篇地址在:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2420610
本文上篇基本上是 RTTI 入门介绍,续篇介绍了所有 TypInfo.pas 中的函数,附加了 Classes.pas、Graphics.pas、Controls.pas 中的几个 RTTI 相关函数。对于关键函数的代码提供汇编注释。希望本文覆盖了 Delphi 中 80% 的 RTTI 函数。时间仓促,错误难免,敬请批评指正。
本文排版格式为:
正文由窗口自动换行;所有代码以 80 字符为边界;中英文字符以空格符分隔。 (作者保留对本文的所有权利,未经作者同意请勿在在任何公共媒体转载。) 目 录 ⊙ GetTypeData 函数 ⊙ GetPropInfo 函数 ⊙ FindPropInfo 函数 ⊙ GetPropInfos 函数 ⊙ SortPropList 函数 ⊙ GetPropList 函数
------------------------------------------------------ ⊙ GetObjectPropClass 函数 ⊙ PropType / PropIsType 函数 ⊙ IsPublishedProp 函数 ⊙ IsStoredProp 函数
⊙ FreeAndNilProperties 函数
⊙ SetToString / StringToSet 函数
⊙ GetEnumName / GetEnumValue / GetEnumNameValue 函数 ------------------------------------------------------ ⊙ GetOrdProp 函数详解 ⊙ SetOrdProp 函数
⊙ GetEnumProp / SetEnumProp 函数 ⊙ GetSetProp / SetSetProp 函数
⊙ GetObjectProp / SetObjectProp 函数 ⊙ GetStrProp / SetStrProp 函数
⊙ GetFloatProp / SetFloatProp 函数 ⊙ GetPropValue / SetPropValue 函数 ⊙ TPublishableVariantType class
------------------------------------------------------ ⊙ RegisterClass / FindClass 系列函数 (Classes.pas) ⊙ IdentToInt / IntToIdent 系列函数 (Classes.pas) 正 文 ⊙ GetTypeData 函数
11
GetTypeData 函数根据 TTypeInfo 指针获得 TTypeData 的地址。
function GetTypeData(TypeInfo: PTypeInfo): PTypeData; asm
XOR EDX,EDX ; EDX 清零
MOV DL,[EAX].TTypeInfo.Name.Byte[0] ; 获得 Name 字符串长度 LEA EAX,[EAX].TTypeInfo.Name[EDX+1] ; 获得 TTypeData 的地址 end; ⊙ GetPropInfo 函数
GetPropInfo 函数用于获得属性的 RTTI 指针 PPropInfo。它有四种重载形式,后面三种重载的实现都是调用第一种形式。AKinds 参数用于限制属性的类型,如果得到的 PPropInfo 不属于指定的类型,则返回 nil。
function GetPropInfo(TypeInfo: PTypeInfo; const PropName: string): PPropInfo;
function GetPropInfo(Instance: TObject; const PropName: string; AKinds: TTypeKinds = []): PPropInfo;
function GetPropInfo(AClass: TClass; const PropName: string; AKinds: TTypeKinds = []): PPropInfo;
function GetPropInfo(TypeInfo: PTypeInfo; const PropName: string; AKinds: TTypeKinds): PPropInfo; ⊙ FindPropInfo 函数 FindPropInfo 函数根据属性名称获得属性的 RTTI 指针,它只是在 GetPropInfo 函数的基础上加上了错误检查功能,如果没有属性 RTTI 信息,则触发 EPropertyError 异常。
function FindPropInfo(Instance: TObject; const PropName: string): PPropInfo; function FindPropInfo(AClass: TClass; const PropName: string): PPropInfo; ⊙ GetPropInfos 函数
GetPropInfos 函数的功能是把一个类(class)所有属性 RTTI 指针 PPropInfo 填充至传入的参数 PPropList 数组中。
注意:这个函数不负责分配该数组的内容,使用前必须根据属性的数量分配足够的空间。该数组结束后必须清除分配的内容。
procedure GetPropInfos(TypeInfo: PTypeInfo; PropList: PPropList);
注:使用 GetPropList 实现相同的功能更方便。 ⊙ SortPropList 函数
SortPropList 可以对 GetPropInfos 函数填充的属性信息指针数组按属性名称排序。
12