我将来自一系列对象的小型接口存储到单个TInterfaceList“store”中,目的是向最终用户提供特定接口类型的列表,因此每个接口都将公开“GetName”函数,但所有其他方法对于该接口类型是唯一的。例如,这里有两个接口:
IBase = interface
//----------------------------------------
function GetName : string;
//----------------------------------------
end;
IMeasureTemperature = interface(IBase)
//------------------------------------
function MeasureTemperature : double;
//----------------------------------------
end;
IMeasureHumidity = interface(IBase)
//----------------------------------------
function MeasureHumidity: double;
//----------------------------------------
end;
我把几个接口放到一个TInterfaceList中,然后我想扫描列表中的特定接口类型(例如'IMeasureTemperature'),构建另一个指向导出这些接口的对象的指针列表。我不想对这些对象的位置做任何假设,有些可能会导出多种类型的接口。我知道我可以使用类似以下内容的类层次结构执行此操作:
If FList[I] is TMeasureTemperature then ..
但是我想用接口类型做一些类似的事情,这可能吗?
答案 0 :(得分:6)
只需使用支持,如下:
var
oMTIntf: IMeasureTemperature;
...
If Supports(FList[I], IMeasureTemperature, oMTIntf) then ..
答案 1 :(得分:2)
您可以在SysUtils中使用Supports
函数,它们非常安全(除非您在单位化内存上尝试它们)并且您只需要一个您尝试强制转换为的接口类型的目标变量:
procedure DoSomethingInList(AList: IInterfaceList;);
var
i: Integer;
liItem: IInterface;
liMeasureTemp: IMeasureTemperature;
liMeasureHumi: IMeasureHumidity;
begin
AList.Lock;
try
for i := 0 to AList.Count - 1 do
begin
liItem := AList[i];
if Supports(liItem, IMeasureTemperature, liMeasureTemp) then
//... liMeasureTemp.MeasureTemperature ...
else if Supports(liItem, IMeasureHumidity, liMeasureHumi) then
//... liMeasureHumi.MeasureHumidity ...
else
//...
end;
finally
AList.Unlock;
end;
end;
答案 2 :(得分:2)
我想这可能会满足您的需求。
function InterfaceRefIsInterface(Intf : IUnknown; ExpectedIntf : TGUID) : Boolean;
var vReference : IUnknown;
begin
if Supports(Intf, ExpectedIntf, vReference) then
Result := Intf = vReference
else
Result := False;
end;
我不确定当Intf和ExpectedIntf相互继承时函数的行为如何,但如果Intf与ExpectedIntf完全匹配,则返回TRUE。
在你的例子中,IMeasureHumidity在IMeasureTemperature上不会返回true,但我不确定它会如何对IBase做出反应。根据初步测试,它也将在IBase上返回FALSE。