Delphi 的RTTI机制浅探 联系客服

发布时间 : 星期五 文章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