您的位置:首页 > 其它

我的一个 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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: