• delphi RTTI机制学习(一)


    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.
  • 相关阅读:
    统计数据持久化
    缓存层的实现
    C++语法疑点
    为什么需要定义虚的析构函数?
    C++ shared_ptr deleter的实现
    条件变量
    ubuntu  输入时弹出剪切板候选项
    leetcode Bitwise AND of Numbers Range
    C/C++ 字符串 null terminal
    C++ inline weak symbol and so on
  • 原文地址:https://www.cnblogs.com/pengshaomin/p/3036999.html
Copyright © 2020-2023  润新知