如何在任意类型上调用GetEnumerator?

时间:2009-08-24 09:03:04

标签: delphi methods call rtti

我正在编写一个能够显示任何数据列表的控件。我想做的是模仿for-in构造,我检查一个包含Current属性和MoveNext方法的公共GetEnumerator函数。

我已经确定了以下内容:

  1. 我可以通过在对象上调用MethodAddress来检查方法的存在性。如果我得到地址,则该方法存在。
  2. 我可以使用RTTI来检查方法的返回类型。
  3. 我可以使用RTTI来检查属性并阅读它。
  4. 虽然介于两者之间,但我缺少一些信息:

    1. 如果给出地址,我如何调用该方法?我只是写一个定义(就像我要导入的那样),转换地址并调用它吗?
    2. 检查方法的返回类型需要使用其PTypeInfo调用GetTypeData。我通过在类型上调用TypeInfo来获取PTypeInfo。那么如何给出给定方法的PTypeInfo,只给出它的地址?

2 个答案:

答案 0 :(得分:2)

  1. 要调用该方法,请获取返回的地址并将其放入TMethod的代码指针中。将对象放入Data指针,然后将其强制转换为具有正确签名的方法指针。
  2. 要分析函数的签名,您需要一些非常复杂的RTTI。有关详细信息,请参阅http://hallvards.blogspot.com/2006/05/hack-10-getting-parameters-of.html。但请注意底部的警告:
  3.   

    请注意,这仅适用于   实例(或其中一个组件)   还有一个已发布的财产   指向已发布的方法。该   好消息是,情况就是如此   大多数现有已公布的方法 - 如此   作为TForm上的事件处理程序   实例。坏消息是这个   不会是这样的   我们想要发布的方法   在运行时动态调用(因此   不会被分配给任何事件。)

    因此,在当前的RTTI模型下,您可能无法做到这一点。但是Delphi 2010应该有一个扩展的RTTI系统,这将使你能够更轻松地完成这样的事情,并且它应该是RSN。 (曾经有一个关于Embarcadero网站的倒计时倒计时,今晚午夜倒计时。他们已经取消了它,所以我不确定这是否仍然是官方发布日期。)

答案 1 :(得分:1)

首先,请注意RTTI仅适用于已发布的属性和方法。

要调用MethodAdress检索的方法,只需执行:

TMyMethod = procedure (Self : TObject; const Param : String);
...
var
  MyMethod : TMyMethod;
...
MyMethod := Obj.MethodAdress ('MethodName');
if Assigned (MyMethod) then
  MyMethod (Obj, 'Hallo');

关于你的第二个问题,这可能会有所帮助:

Link