将现有方法的名称从一个Unit分配给另一个Unit中的通用TMethod

时间:2014-03-24 17:46:54

标签: delphi delphi-xe4

基本上,我有一个应用程序,它将从INI文件中检索信息,并且该过程的一部分包括提取在INI中存储的名称 - 在另一个单元内的全局范围内声明的某些过程。

我使用以下内容来获取SQL方法:

MyIni.ReadString('SQL', SubStr + '_Insert, ''); 

SubStr是我想要的数据类型,例如“titles”,它以我想要的SQL过程类型为前缀,在本例中为“_Insert”,因此,我的请求可以看作:

MyIni.ReadString('SQL', 'titles_Insert', ''); 

然后将检索INI内显示的相应SQL 过程名称“InsertTitlesSql”:

[SQL]    
titles_Insert=InsertTitlesSql

我有一个单元列出了我们使用的SQL过程。 像这样:

unit uSqlLibrary;

interface
  function InsertTitlesSql: string;

implementation

function InsertTitlesSql: string;
begin
  {
    INSERT INTO TITLES (ENGLISH, AFRIKAANS, KEY)
    VALUES (:english,
            :afrikaans,
            :key)
  }
  Result := ''
    +'INSERT INTO TITLES (ENGLISH, AFRIKAANS, KEY) '
    +'VALUES (:english, '
    +'        :afrikaans, '
    +'        :key) ';
end;

end.

我尝试了TGenericContainer没有任何成功,我也尝试了MethodAddress但我不知道如何告诉MethodAddress查看没有要引用的Object的其他单元(例如Form1.MethodAddress())我最好到目前为止的结果是:

type
   TExec = procedure of object;

procedure TForm1.Button1Click(Sender: TObject);
var
  M : TMethod ;
  E : TExec ;
begin
  M.Code := @Test; // Where "Test" is a procedure inside a secondary Unit. 
  E := TExec(M);
  E;
end;

我要做的是按照我想要的名称获取SQL过程(函数 InsertTitlesSql :string;)并将其分配给行为方式相同的泛型方法。

我的团队负责人说他不想编辑uSqlLibrary;所以我不能那样做,而是想过用方法的名字来代替。欢迎任何其他建议。

希望这很清楚。对不起,如果不是(我使用的术语不太好xD)。如果可以的话,我会尽力详细说明你的问题。

1 个答案:

答案 0 :(得分:3)

您无法使用RTTI枚举具有全局范围的过程。您可以枚举方法,因此可以将全局过程转换为静态类方法。

但是,您还声明您的团队负责人不希望您更改uSqlLibrary。在我看来,这似乎有点短视。随意告诉他/她我是这么说的。

无论如何,如果您无法更改uSqlLibrary,则无法使用RTTI。因此,您需要构建自己的查找表。使用通用字典:

uses
  System.Generics.Collections;

var
  ProcTable: TDictionary<string, TProc>;

以通常的方式实例化它。在程序启动时添加功能:

....
ProcTable.Add('InsertTitlesSql', InsertTitlesSql);
....

当你需要查看并打电话时,请执行以下操作:

var
  Proc: TProc;
....
if not ProcTable.TryGetValue(ProcName, Proc) then
  raise EProcNotFound.CreateFmt(...);
Proc();

默认情况下,用于密钥的默认相等比较器区分大小写。因此,您可以选择提供自定义相等比较器,用于比较没有区分大小写的键。