我的一个 RTTI 练习(参照 d5开发人员指南)
2006-04-05 15:41
351 查看
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids, DBGrids, DB, DBTables;
type
TForm1 = class(TForm)
Memo1: TMemo;
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses typinfo;
{$R *.dfm}
type
PParamRecord = ^TParamRecord;
TParamRecord = record
Flags : TParamFlags;
{
TParamFlag = (pfVar, pfConst, pfArray, pfAddress, pfReference, pfOut);
TParamFlags = set of TParamFlag;
}
ParamName:shortstring;
TypeName :shortString;
end;
procedure getBaseMethodInfo(aTypeInfo:PTypeInfo;aStrings:TStrings);
var
MTD:PTypeData;
EnumName:string;
begin
MTD := getTypeData(aTypeInfo);
with aStrings do
begin
add(format('Class Name %s',[aTypeInfo.name]));
EnumName := getEnumName(TypeInfo(TTypeKind),Integer(aTypeinfo.kind));
add(format('Kind %s',[EnumName]));
add(format('Num Parameters:%d',[MTD.Propcount]));
end;
end;
procedure getMethodDefinition(aTypeInfo:PTypeInfo;aStrings:TStrings);
var
MethodTypeData : PTypeData;
MethodDefine :string;
ParamRecord : PParamRecord;
TypeStr : ^shortstring;
ReturnStr : ^shortString;
i , j: integer;
s : string;
s2: string;
P:PParamRecord;
begin
MethodTypeData := getTypeData(aTypeInfo);
case MethodTypedata.MethodKind of
typInfo.mkProcedure : MethodDefine := 'procedure';
typinfo.mkFunction : MethodDefine := 'function';
typinfo.mkConstructor : MethodDefine := 'constructor';
typinfo.mkDestructor : MethodDefine := 'destructor';
typinfo.mkClassProcedure : MethodDefine := ' class procedure';
typinfo.mkClassFunction : MethodDefine := ' class function';
end;
ParamRecord := @MethodTypeData.paramList;
// ParamList 是一个字符数组 上面是取得这个数组的地址
{
tkMethod: (
MethodKind: TMethodKind;
ParamCount: Byte;
ParamList: array[0..1023] of Char
//-------------------------------
ParamList: array[1..ParamCount] of
record
Flags: TParamFlags;
ParamName: ShortString;
TypeName: ShortString;
end;
}
i := 1;
//-------------------------------------------------------------------------
// ParamList 是一个字符数组,试试打印一下它的全部的字符出来
getmem(p,sizeof(TParamRecord));
//for j := low(MethodTypeData.ParamList) to high(MethodTypeData.ParamList) do
for j := 0 to 0 do
begin
//s := s+MethodTypeData.ParamList[j];
// 试着用 paramRecord 来进一步得到记录
p := @MethodTypeData.ParamList[j];
s2 := getEnumName(TypeInfo(TParamFlag),Integer(TParamFlag(p.Flags)));
form1.Memo1.Lines.Add('flags:'+s2+' paramName:'+p.ParamName+' TypeName:'+p.TypeName);
end;
freemem(p,sizeof(TParamRecord));
//form1.Memo1.Lines.Add(s);
// 由于这个数组的每个元素也是一个 TParamRecord 类型的数组,所以在取数据时有
// 点问题
//-------------------------------------------------------------------------
while i <= MethodTypeData.ParamCount do
begin
if i = 1 then // i 没有变化,先加上一个 (
MethodDefine := MethodDefine+'(';
if pfconst in ParamRecord.Flags then
MethodDefine := MethodDefine+'const';
if typInfo.pfVar in ParamRecord.Flags then
MethodDefine := MethodDefine+'var';
if typInfo.pfArray in ParamRecord.Flags then
MethodDefine := MethodDefine+'Array of';
if TypInfo.pfOut in ParamRecord.Flags then
MethodDefine := MethodDefine+'out';
if TypInfo.pfAddress in ParamRecord.Flags then
MethodDefine := MethodDefine+'*address';
// 试了试 用 ParamRecord.ParamName 不带 ^ ,也能正常运行,这里对 ParamRecord.ParamName
// 与 ParamRecord^.ParamName 的区别不理解,用程序试了试,这两种的运行结果是一样的
typeStr := Pointer(Integer(@ParamRecord^.ParamName)+Length(ParamRecord^.ParamName)+1);
MethodDefine := Format('%s%s:%s',[MethodDefine,ParamRecord.paramName,typeStr^]);
inc(i);
// ParamList 是一个 TParamRecord 记录的数组,
// integer(ParamRecord) 取得 ParamRecord 的首地址 加上
// sizeof(TParamFlags) 取得 flags 的大小 加上
// (length(ParamRecord.ParamName)+1) 取得 paramName 的长度加上 #0 这个字符
// Length(TypeStr^)+1 取得 TypeStr的长度加上 #0
// 这里的 #0 应该是和 pchar 的以0结尾的字符串一样的
ParamRecord := PParamRecord(Integer(paramRecord)+sizeof(TparamFlags)
+(Length(ParamRecord.ParamName)+1)+(Length(TypeStr^)+1));
//--------------
if i<=MethodTypeData.ParamCount then
begin
MethodDefine := MethodDefine+';';
end
else
begin
MethodDefine := MethodDefine+')';
end;
if MethodTypeData.MethodKind = mkFunction then
begin
ReturnStr := Pointer(ParamRecord);
MethodDefine := format('%s:%s;',[MethodDefine,ReturnStr]);
end
else
begin
MethodDefine := MethodDefine+';';
end;
end;
with aStrings do
begin
add(MethodDefine);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
with self.ListBox1.Items do
begin
addObject('TNotifyEvent',TypeInfo(TNotifyEvent));
addObject('TMouseEvent',TypeInfo(TMouseEvent));
end;
//db.TBCDField(table1.FieldByName('buyin_amt')).DisplayFormat := '##,##.##';
end;
procedure TForm1.ListBox1Click(Sender: TObject);
begin
self.Memo1.Lines.Clear;
with self.ListBox1 do
begin
getBaseMethodInfo(PTypeInfo(items.Objects[ItemIndex]),self.Memo1.Lines);
GetMethodDefinition(PTypeInfo(items.Objects[ItemIndex]),self.Memo1.Lines);
end;
end;
end.
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids, DBGrids, DB, DBTables;
type
TForm1 = class(TForm)
Memo1: TMemo;
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses typinfo;
{$R *.dfm}
type
PParamRecord = ^TParamRecord;
TParamRecord = record
Flags : TParamFlags;
{
TParamFlag = (pfVar, pfConst, pfArray, pfAddress, pfReference, pfOut);
TParamFlags = set of TParamFlag;
}
ParamName:shortstring;
TypeName :shortString;
end;
procedure getBaseMethodInfo(aTypeInfo:PTypeInfo;aStrings:TStrings);
var
MTD:PTypeData;
EnumName:string;
begin
MTD := getTypeData(aTypeInfo);
with aStrings do
begin
add(format('Class Name %s',[aTypeInfo.name]));
EnumName := getEnumName(TypeInfo(TTypeKind),Integer(aTypeinfo.kind));
add(format('Kind %s',[EnumName]));
add(format('Num Parameters:%d',[MTD.Propcount]));
end;
end;
procedure getMethodDefinition(aTypeInfo:PTypeInfo;aStrings:TStrings);
var
MethodTypeData : PTypeData;
MethodDefine :string;
ParamRecord : PParamRecord;
TypeStr : ^shortstring;
ReturnStr : ^shortString;
i , j: integer;
s : string;
s2: string;
P:PParamRecord;
begin
MethodTypeData := getTypeData(aTypeInfo);
case MethodTypedata.MethodKind of
typInfo.mkProcedure : MethodDefine := 'procedure';
typinfo.mkFunction : MethodDefine := 'function';
typinfo.mkConstructor : MethodDefine := 'constructor';
typinfo.mkDestructor : MethodDefine := 'destructor';
typinfo.mkClassProcedure : MethodDefine := ' class procedure';
typinfo.mkClassFunction : MethodDefine := ' class function';
end;
ParamRecord := @MethodTypeData.paramList;
// ParamList 是一个字符数组 上面是取得这个数组的地址
{
tkMethod: (
MethodKind: TMethodKind;
ParamCount: Byte;
ParamList: array[0..1023] of Char
//-------------------------------
ParamList: array[1..ParamCount] of
record
Flags: TParamFlags;
ParamName: ShortString;
TypeName: ShortString;
end;
}
i := 1;
//-------------------------------------------------------------------------
// ParamList 是一个字符数组,试试打印一下它的全部的字符出来
getmem(p,sizeof(TParamRecord));
//for j := low(MethodTypeData.ParamList) to high(MethodTypeData.ParamList) do
for j := 0 to 0 do
begin
//s := s+MethodTypeData.ParamList[j];
// 试着用 paramRecord 来进一步得到记录
p := @MethodTypeData.ParamList[j];
s2 := getEnumName(TypeInfo(TParamFlag),Integer(TParamFlag(p.Flags)));
form1.Memo1.Lines.Add('flags:'+s2+' paramName:'+p.ParamName+' TypeName:'+p.TypeName);
end;
freemem(p,sizeof(TParamRecord));
//form1.Memo1.Lines.Add(s);
// 由于这个数组的每个元素也是一个 TParamRecord 类型的数组,所以在取数据时有
// 点问题
//-------------------------------------------------------------------------
while i <= MethodTypeData.ParamCount do
begin
if i = 1 then // i 没有变化,先加上一个 (
MethodDefine := MethodDefine+'(';
if pfconst in ParamRecord.Flags then
MethodDefine := MethodDefine+'const';
if typInfo.pfVar in ParamRecord.Flags then
MethodDefine := MethodDefine+'var';
if typInfo.pfArray in ParamRecord.Flags then
MethodDefine := MethodDefine+'Array of';
if TypInfo.pfOut in ParamRecord.Flags then
MethodDefine := MethodDefine+'out';
if TypInfo.pfAddress in ParamRecord.Flags then
MethodDefine := MethodDefine+'*address';
// 试了试 用 ParamRecord.ParamName 不带 ^ ,也能正常运行,这里对 ParamRecord.ParamName
// 与 ParamRecord^.ParamName 的区别不理解,用程序试了试,这两种的运行结果是一样的
typeStr := Pointer(Integer(@ParamRecord^.ParamName)+Length(ParamRecord^.ParamName)+1);
MethodDefine := Format('%s%s:%s',[MethodDefine,ParamRecord.paramName,typeStr^]);
inc(i);
// ParamList 是一个 TParamRecord 记录的数组,
// integer(ParamRecord) 取得 ParamRecord 的首地址 加上
// sizeof(TParamFlags) 取得 flags 的大小 加上
// (length(ParamRecord.ParamName)+1) 取得 paramName 的长度加上 #0 这个字符
// Length(TypeStr^)+1 取得 TypeStr的长度加上 #0
// 这里的 #0 应该是和 pchar 的以0结尾的字符串一样的
ParamRecord := PParamRecord(Integer(paramRecord)+sizeof(TparamFlags)
+(Length(ParamRecord.ParamName)+1)+(Length(TypeStr^)+1));
//--------------
if i<=MethodTypeData.ParamCount then
begin
MethodDefine := MethodDefine+';';
end
else
begin
MethodDefine := MethodDefine+')';
end;
if MethodTypeData.MethodKind = mkFunction then
begin
ReturnStr := Pointer(ParamRecord);
MethodDefine := format('%s:%s;',[MethodDefine,ReturnStr]);
end
else
begin
MethodDefine := MethodDefine+';';
end;
end;
with aStrings do
begin
add(MethodDefine);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
with self.ListBox1.Items do
begin
addObject('TNotifyEvent',TypeInfo(TNotifyEvent));
addObject('TMouseEvent',TypeInfo(TMouseEvent));
end;
//db.TBCDField(table1.FieldByName('buyin_amt')).DisplayFormat := '##,##.##';
end;
procedure TForm1.ListBox1Click(Sender: TObject);
begin
self.Memo1.Lines.Clear;
with self.ListBox1 do
begin
getBaseMethodInfo(PTypeInfo(items.Objects[ItemIndex]),self.Memo1.Lines);
GetMethodDefinition(PTypeInfo(items.Objects[ItemIndex]),self.Memo1.Lines);
end;
end;
end.
相关文章推荐
- Delphi中动态链接库两种调用方式的比较 ------D5开发人员指南上的
- 为什么微软的开发人员需要一个风格指南
- .NET Framework 开发人员指南——如何:提高性能
- 一个不错的苹果开发人员论坛
- PX4(PIXHAWK)源码开发人员文档(三)——进程间通讯的开发者指南
- 去年这时候辞退了一个开发人员,不知道他现在是否还在写程序了,可以对比一下编程水平
- 为Android开发人员推荐一个拥有大量代码库和工具的新地方
- 黑莓开发人员必读资料 - BlackBerry - 开发指南- 手册和指南
- 3月27号周五课堂练习:结对开发----返回一个整数数组中最大子数组的和三
- 一个SharePoint开发人员必备的工具
- 如何做一个让开发人员看得起的测试人员
- 现在,为什么连一个 JavaScript 的厌恶者都认为:每个开发人员都应该学习 JavaScript
- 面向 Java 开发人员的 Scala 指南: 面向对象的函数编程
- 做一个运动控制软件开发人员需要具备的条件!
- 介绍一个MonoTouch开发的伦敦官方城市指南应用
- 介绍一个MonoTouch开发的伦敦官方城市指南应用
- 作为一个前端开发人员,来罗嗦两句
- 面向 Java 开发人员的 Scala 指南: 深入了解 Scala 并发性
- 成为一个高效的web开发人员,只需要三步
- 做一个开发人员认可的测试人员(系列3)--谈谈自动化测试框架