【发布时间】:2011-11-22 02:27:31
【问题描述】:
我知道 Delphi XE2 有新的 TVirtualInterface 用于在运行时创建接口的实现。不幸的是,我没有使用 XE2,我想知道在旧版本的 Delphi 中做这种事情涉及什么样的黑客。
假设我有以下界面:
IMyInterface = interface
['{8A827997-0058-4756-B02D-8DCDD32B7607}']
procedure Go;
end;
是否可以在运行时不借助编译器绑定到这个接口?
TMyClass = class(TObject, IInterface)
public
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
procedure Go; //I want to dynamically bind IMyInterface.Go here
end;
我尝试了一个简单的硬演员:
var MyInterface: IMyInterface;
begin
MyInterface := IMyInterface(TMyClass.Create);
end;
但编译器会阻止这一点。
然后我尝试了as 演员表,它至少编译了:
MyInterface := TMyClass.Create as IMyInterface;
所以我想关键是让QueryInterface 返回一个有效指针,指向被查询接口的实现。我将如何在运行时构建一个?
我已经研究过 System.pas,所以我至少对 GetInterface、GetInterfaceEntry 和 InvokeImplGetter 的工作方式有一定的了解。 (谢天谢地,Embacadero 选择离开帕斯卡源以及优化的程序集)。我可能没有正确阅读它,但似乎存在偏移量为零的接口条目,在这种情况下,可以使用InvokeImplGetter 分配接口的另一种方法。
我的最终目标是模拟支持反射的语言中提供的动态代理和模拟的一些功能。如果我可以成功地绑定到与接口具有相同方法名称和签名的对象,那将是重要的第一步。这甚至可能吗?还是我找错了树?
【问题讨论】:
-
如果您需要这样做,那么 XE2 是您的最佳选择。使用 TVirtualInterface 非常简单。没有那门课,这将是痛苦和挣扎。 DelphiMocks 项目中有一个尝试:bit.ly/o9GJVW
-
如果我成功了,我打算将它贡献给 DelphiMocks。
-
也许this question 对你来说很有趣。
-
我什至不知道这个 XE2 功能。对于 Mock/UnitTest 而言,这非常令人兴奋!
-
在这种情况下您可以使用调度接口吗?这将比本机 COM vtable 接口容易一些。我还想到 DCOM 必须能够在其代理生成和编组功能中做到这一点。但这是相当先进的东西。
标签: delphi binding dynamic interface