代码之家  ›  专栏  ›  技术社区  ›  Brian Frost

如何在Delphi TinterfaceList中存储和定位多个接口类型

  •  6
  • Brian Frost  · 技术社区  · 14 年前

    我将一系列对象中的小接口存储到单个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 ..
    

    但是我想用接口类型做一些类似的事情,这是可能的吗?

    3 回复  |  直到 14 年前
        1
  •  2
  •   Ken Bourassa    14 年前

    我想这可以满足你的需要。

    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上返回错误。

        2
  •  6
  •   da-soft    14 年前

    只需使用支架,如:

    var
      oMTIntf: IMeasureTemperature;
    ...
      If Supports(FList[I], IMeasureTemperature, oMTIntf) then .. 
    
        3
  •  2
  •   Viktor Svub    14 年前

    你可以使用 Supports 在sysutils中,它们是非常安全的(除非您在统一的内存中进行尝试),并且您只需要一个目标变量,它与您尝试强制转换到的接口类型完全相同:

    
    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;