zoukankan      html  css  js  c++  java
  • DELPHI RTTI实现非可视的功能插件

    思路:通过数据字典定义BPL包名,然后定义BPL包里面的类名,然后定义类里面的方法名,最后定义方法的参数值。

    可实现动态加载BPL,调用哪个BPL的哪个类的哪个方法并给该方法赋给指定的参数值,如果是函数还可以取得函数的返回值。

    应用场合之一:中间件实现非可视功能插件。

    下面来DEMO码子。

    首先动态加载BPL包:

    bplName := TPlug(TdxBarButton(Sender).Tag).bplName;
      if FileExists(bplName) then
      begin
        unitClass := string(TPlug(TdxBarButton(Sender).Tag).UnitCalss);
        plugName := TPlug(TdxBarButton(Sender).Tag).description;
        powerValue := TPlug(TdxBarButton(Sender).Tag).powerValue;
        if not bplList.ContainsKey(bplName) then
        begin
          h := LoadPackage(bplName);
          if h = 0 then
            ShowTrayHint(bplName + '包加载失败')
          else
            bplList.Add(bplName, h);
        end;

    然后获取BPL的对象

    var
      LContext: TRttiContext;
      LPackage: TRttiPackage;
      LClass: TRttiInstanceType;
      aForm: TCustomForm;

    begin

    LContext := TRttiContext.Create;
        try
          for LPackage in LContext.GetPackages() do
          begin
            if SameText(ExtractFileName(LPackage.Name), bplFile) then
            begin

              LClass := LPackage.FindType(unitClass) as TRttiInstanceType;
              aForm := LClass.MetaclassType.Create as TCustomForm;

          end

       finally
          LContext.Free;
        end;

    最后传递参数调用类的方法

      TMyClass = class(TComponent)
      public
        procedure msg(const str: string);
        function Add(const a,b: Integer): Integer;
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.dfm}

    { TMyClass }

    procedure TMyClass.msg(const str: string);
    begin
      MessageDlg(str, mtInformation, [mbYes], 0);
    end;

    function TMyClass.Add(const a, b: Integer): Integer;
    begin
      Result := a + b;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var
      obj: TMyClass;
      t: TRttiType;
      m1,m2: TRttiMethod;
      r: TValue; //TRttiMethod.Invoke 的返回类型
    begin
      t := TRttiContext.Create.GetType(TMyClass);

      {获取 TMyClass 类的两个方法}
      m1 := t.GetMethod('msg'); {procedure}
      m2 := t.GetMethod('Add'); {function}

      obj := TMyClass.Create(Self); {调用需要依赖一个已存在的对象}

      {调用 msg 过程}
      m1.Invoke(obj, ['Delphi 2010']); {将弹出信息框}

      {调用 Add 函数}
      r := m2.Invoke(obj, [1, 2]); {其返回值是个 TValue 类型的结构}
      ShowMessage(IntToStr(r.AsInteger)); {3}

      obj.Free;
    end;

    代码只是为了演示这么个意思,你懂的。

    以上的一切都是通过字典定义,RTTI运行时根据字典动态调用,如果你的开发框架里面或者中间件里面这样实现,简直帅呆了!

     

  • 相关阅读:
    开通博客
    简单、方便、实用的日志记录系统
    浅谈近两年工作
    前端构建神器之 gulp
    CSS 3 transition属性
    angular.extend相关知识
    angular.element相关知识
    angularJS之$apply()方法
    Jquery选择器
    Jquery选择器小节
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/4889665.html
Copyright © 2011-2022 走看看