简单测试运行时类信息(RTTI),附详细例子

新建一个单元文件,填写如下代码,然后保存为 ClassInfoUnit.pas,这里定义了一个结构,用来读取指定类的信息。

[delphi] view plaincopy

  1. unit ClassInfoUnit;
  2. interface
  3. uses
  4. Classes, TypInfo;
  5. type
  6. { 存放类属性的动态数组 }
  7. PropInfoArray = array of PPropInfo;
  8. { 用法:首先声明该结构的变量,然后通过 Create 函数或 Target 属性指定要获取 }
  9. { 信息的类,然后就可以通过 public 中的属性或方法来获取该类的各种信息了 }
  10. TClassInfo = record      { use TypInfo }
  11. private
  12. { 属性:要获取其运行时信息(RTTI)的类 }
  13. FTarget: TClass;
  14. { 属性:指向存放类信息的指针 }
  15. FTypeInfo: PTypeInfo;
  16. { 属性:指向存放类数据的指针 }
  17. FDataInfo: PTypeData;
  18. { 类属性(property)的个数 }
  19. FPropertyCount: Cardinal;
  20. { 类属性列表(数组) }
  21. FPropertyList: PropInfoArray;
  22. { 设置 FTarget }
  23. procedure SetTarget(aClass: TClass);
  24. { 读取 PropertyTypes[Index] }
  25. function GetPropTypes(Index: Integer): PTypeInfo;
  26. public
  27. { 构造函数,用来设置要获取其信息的对象 }
  28. procedure Create(aObj: TObject); overload;
  29. { 构造函数,用来设置要获取其信息的类 }
  30. procedure Create(aClass: TClass); overload;
  31. { 获取类的所有属性和事件 }
  32. function GetAllProperties: string;
  33. { 获取类的所有属性 }
  34. function GetPropList: string;
  35. { 获取类的所有事件 }
  36. function GetMethodList: string;
  37. { 指向类信息的指针 }
  38. property TypeInfo: PTypeInfo read FTypeInfo;
  39. { 指向类数据的指针 }
  40. property DataInfo: PTypeData read FDataInfo;
  41. { 属性:要获取其运行时信息(RTTI)的类 }
  42. property Target: TClass read FTarget write SetTarget;
  43. { 类的所有属性信息列表 }
  44. property PropertyList: PropInfoArray read FPropertyList;
  45. { 类的所有属性类型列表 }
  46. property PropertyTypes[Index: Integer]: PTypeInfo read GetPropTypes;
  47. { 类的属性总个数 }
  48. property PropertyCount: Cardinal read FPropertyCount;
  49. end;
  50. implementation
  51. { 构造函数 }
  52. procedure TClassInfo.Create(aObj: TObject);
  53. begin
  54. if aObj = nil then
  55. Create(nil)
  56. else
  57. Create(aObj.ClassType);
  58. end;
  59. { 构造函数 }
  60. procedure TClassInfo.Create(aClass: TClass);
  61. begin
  62. Target := aClass;
  63. end;
  64. { 私有:更改要操作的类 }
  65. procedure TClassInfo.SetTarget(aClass: TClass);
  66. begin
  67. if FTarget = aClass then
  68. Exit;
  69. FTarget := aClass;
  70. if Assigned(FTarget) then
  71. begin
  72. FTypeInfo := aClass.ClassInfo;
  73. FDataInfo := GetTypeData(FTypeInfo);
  74. FPropertyCount := FDataInfo.PropCount;
  75. SetLength(FPropertyList, FPropertyCount);
  76. GetPropInfos(FTypeInfo, PPropList(FPropertyList));
  77. end
  78. else
  79. begin
  80. FTypeInfo := nil;
  81. FDataInfo := nil;
  82. FPropertyCount := 0;
  83. SetLength(FPropertyList,0);
  84. end;
  85. end;
  86. { 私有:获取属性的类型信息 }
  87. function TClassInfo.GetPropTypes(Index: Integer): PTypeInfo;
  88. begin
  89. Result := nil;
  90. if FPropertyCount = 0 then
  91. Exit;
  92. Result := FPropertyList[Index].PropType^;
  93. end;
  94. { 获取所有属性和事件列表 }
  95. function TClassInfo.GetAllProperties: string;
  96. var
  97. I: Integer;
  98. Strs: TStringList;
  99. begin
  100. if FPropertyCount = 0 then
  101. Exit;
  102. Strs := TStringList.Create;
  103. try
  104. for I := 0 to PropertyCount - 1 do
  105. Strs.Add(PropertyList[I].Name);
  106. Result := Strs.Text;
  107. finally
  108. Strs.Free;
  109. end;
  110. end;
  111. { 获取属性列表 }
  112. function TClassInfo.GetPropList: string;
  113. var
  114. I: Integer;
  115. Strs: TStringList;
  116. begin
  117. if FPropertyCount = 0 then
  118. Exit;
  119. Strs := TStringList.Create;
  120. try
  121. for I := 0 to PropertyCount - 1 do
  122. begin
  123. if PropertyTypes[I].Kind <> tkMethod then
  124. Strs.Add(PropertyList[I].Name);
  125. end;
  126. Result := Strs.Text;
  127. finally
  128. Strs.Free;
  129. end;
  130. end;
  131. { 获取事件列表 }
  132. function TClassInfo.GetMethodList: string;
  133. var
  134. I: Integer;
  135. Strs: TStringList;
  136. begin
  137. if FPropertyCount = 0 then
  138. Exit;
  139. Strs := TStringList.Create;
  140. try
  141. for I := 0 to PropertyCount - 1 do
  142. begin
  143. if PropertyTypes[I].Kind = tkMethod then
  144. Strs.Add(PropertyList[I].Name)
  145. end;
  146. Result := Strs.Text;
  147. finally
  148. Strs.Free;
  149. end;
  150. end;
  151. end.

然后创建一个空白窗体,窗体上创建两个 TMemo(mmo1、mmo2)和两个 TButton(btn1、btn2),双击 btn1 和 btn2 ,使用如下代码进行测试(测试在程序运行时 TControl 和 TButton 的 published 属性和方法):

[html] view plaincopy

    1. unit Form1Unit;
    2. interface
    3. uses
    4. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    5. Dialogs, StdCtrls, ExtCtrls;
    6. type
    7. TForm1 = class(TForm)
    8. mmo1: TMemo;
    9. mmo2: TMemo;
    10. btn1: TButton;
    11. btn2: TButton;
    12. procedure btn1Click(Sender: TObject);
    13. procedure btn2Click(Sender: TObject);
    14. private
    15. { Private declarations }
    16. public
    17. { Public declarations }
    18. end;
    19. var
    20. Form1: TForm1;
    21. implementation
    22. {$R *.dfm}
    23. uses
    24. ClassInfoUnit;
    25. { 获取 TControl 的运行时信息 }
    26. procedure TForm1.btn1Click(Sender: TObject);
    27. var
    28. CI: TClassInfo;
    29. begin
    30. Caption := ‘TControl‘;
    31. CI.Create(TControl);
    32. mmo1.Text := CI.GetPropList;
    33. mmo2.Text := CI.GetMethodList;
    34. end;
    35. { 获取 TButton 的运行时信息 }
    36. procedure TForm1.btn2Click(Sender: TObject);
    37. var
    38. CI: TClassInfo;
    39. begin
    40. Caption := ‘TButton‘;
    41. CI.Create(TButton);
    42. mmo1.Text := CI.GetPropList;
    43. mmo2.Text := CI.GetMethodList;
    44. end;
    45. end.

http://blog.csdn.net/stevenldj/article/details/7166455

时间: 2024-12-09 13:34:05

简单测试运行时类信息(RTTI),附详细例子的相关文章

运行时类型信息RTTI

我们在写C++代码的时候经常碰到使用dynamic_cast进行类型转换的情况,也都知道经过dynamic_cast的转换更加安全,因为dynamic_cast进行了类型检查. 但是可能很多人不知道dynamic_cast是C++ 运行时类型信息(RTTI)机制链条上的一个节点. RTTI提供了两个操作符和一个类: dynamic_cast typeid type_info 整个RTTI, 作为一个整体,暴露给程序员的就是这三个元素.因此我们关注的焦点也就在它们身上了. 什么是RTTI 在C++

C++MFC编程笔记day04 运行时类信息和窗口的动态、静态切分

运行时类信息 程序在运行时,获取对象类的信息及类的继承关系 实现: 1.定义类继承自CObject类. 2.类内声明宏DECLARE_DYNAMIC(),类外实现宏IMPLEMENT_DYNAMIC() 3.使用: BOOL IsKindOf(CRuntimeClass* pClass)//对象是否属于某个类 CRuntimeClass* GetRuntimeClass( );//获取对象运行时类信息,经常使用RUNTIME_CLASS(类名)代替. 示例: #include "stdafx.h

运行时类信息机制

// MFCDynimic.cpp : Defines the entry point for the console application.///*运行时类信息机制:在程序运行过程中,可以判断类对象的相关类的信息以及继承派生类.*/ #include "stdafx.h"#include "MFCDynimic.h" class CAnimal:public CObject{DECLARE_DYNAMIC(CAnimal);}; IMPLEMENT_DYNAMI

Java 序列化Serializable详解(附详细例子)

Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.   2.什么情况下需要序列化 a)当你想把的内存中的对象保存到一个文件中或者数据库中时候:b)当你想用套接字在网络上传送对象的时候:c)当你想通过RMI传输对象的时候: 3.如何实现序列化 将需要序列化的类实现Serializable接口就可以了,Seriali

Java 序列化Serializable详解(附详细例子)

1.什么是序列化和反序列化 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程. 2.什么情况下需要序列化  a)当你想把的内存中的对象保存到一个文件中或者数据库中时候: b)当你想用套接字在网络上传送对象的时候: c)当你想通过RMI传输对象的时候: 3.如何实现序列化 将需要序列化的类实现Serializable接口就可以了,Serializable接口中没有任何方法,可以理解为一个标记,即表明

批处理bat脚本编写(附详细例子)

                                                    批处理bat脚本编写(附详细例子) 由于在项目开发的过程中经常需要编写bat脚本,而看大牛们编写的bat脚本简直一头雾水,木有办法,作为bat菜鸟的我只有通过最最简单的例子来熟悉bat脚本中的常用命令,由此来开启我的bat脚本学习之路.... 1.常用命令举例 a.创建文件夹:                         md    D:\mybat       //将在D盘下创建一个名为

Java向上转型和向下转型(附详细例子)

                                            Java向上转型和向下转型(附详细例子) 熬夜整理的关于Java向上和向下转型的例子,非常的通俗易懂哦~~~~ 一.向上转型 package com.sheepmu; class Animal { public void eat() { System.out.println("父类的 eating..."); } } class Bird extends Animal { @Override pub

二叉树的递归遍历和非递归遍历(附详细例子)

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了.这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies .disc_copies都可能会发生. 如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2 mnesia过载分析 1.抛出警告是在mnesia 增加dump

了解运行时类型信息(RTTI)

RTTI需要引用单元TypeInfo GetPropInfo 函数用于获得属性的 RTTI 指针 PPropInfo.它有四种重载形式,后面三种重载的实现都是调用第一种形式.AKinds 参数用于限制属性的类型,如果得到的 PPropInfo 不属于指定的类型,则返回 nil. function GetPropInfo(TypeInfo: PTypeInfo; const PropName: string): PPropInfo; function GetPropInfo(Instance: T