RTTI即运行时类型识别,用来识别动态对象的类型。即使我们仅仅有基类的指针和引用,可以识别出该指针和引用所指向那个类(基类或派生类)。RTTI会带来一定的性能开销。
一、新建一个Console工程
二、定义一个类并引用System.Rtti (我用的是XE3,2010-XE的直接用Rtti)写好后按Ctrl+Shit+G生成方法
三、测试一下 获取类属性(property)
program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Rtti; type TMyClass = class private FID: Integer; FName: String; protected procedure WriteName(); function GetName():String; published property TestProp1:Integer read FID write FID; property TestProp2:String read FName write FName; property TestProp3:String read FName write FName; property TestProp4:Integer read FID write FID; end; { TMyClass } function TMyClass.GetName: String; begin end; procedure TMyClass.WriteName; begin end; var ctx: TRttiContext; t: TRttiType; prop: TRttiProperty; begin ctx := TRttiContext.Create; t := ctx.GetType(TMyClass); for prop in t.GetProperties do begin //获取属性类型 WriteLn(prop.PropertyType.ToString()); end; ctx.Free; ReadLn; end.
如图,获取了Property的四个字段属性
四、测试二获取类成员(private)
var ctx: TRttiContext; t: TRttiType; prop: TRttiProperty; m: TRttiMethod; field: TRttiField; begin ctx := TRttiContext.Create; t := ctx.GetType(TMyClass); for field in t.GetFields do begin //获取成员 WriteLn(field.ToString()); end; ctx.Free; ReadLn; end.
(04 08代表地址偏移)?
还有更多的属性GetMethds获取方法的 自行试验吧
五、动态调用方法
program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Rtti, System.TypInfo; type TMyClass = class private FID: Integer; FName: String; public procedure WriteName(); overload; procedure AddName(const param1: String);overload; function GetName():String; published property TestProp1:Integer read FID write FID; property TestProp2:String read FName write FName; property TestProp3:String read FName write FName; property TestProp4:Integer read FID write FID; end; { TMyClass } function TMyClass.GetName: String; begin WriteLn('调用了GetName过程'); Result := '调用成功'; end; procedure TMyClass.AddName(const param1: String); begin WriteLn('调用了带有参数的AddName方法:' + param1); end; procedure TMyClass.WriteName; begin WriteLn('调用了WriteName方法'); end; var ctx: TRttiContext; t: TRttiType; prop: TRttiProperty; m: TRttiMethod; field: TRttiField; r: TValue; cls: TMyClass; begin ctx := TRttiContext.Create; cls := TMyClass.Create; try t := ctx.GetType(TMyClass); //通过传入方法名获取方法地址 只能取public方法 protected的取不到 m := t.GetMethod('WriteName'); m.Invoke(cls, []); //如果是重载方法报参数不匹配 m := t.GetMethod('AddName'); m.Invoke(cls, ['有参数的']); //调用带有返回值的 m := t.GetMethod('GetName'); r := m.Invoke(cls,[]); case r.Kind of tkString: WriteLn('返回值类型:String'); tkUString: WriteLn('返回值类型:Unicode String'); end; WriteLn('返回值:' + r.ToString()); finally cls.Free; ctx.Free; end; ReadLn; end.