在泛型类中转换为接口delphi

时间:2014-08-01 16:10:39

标签: delphi generics delphi-xe6

我从.NET类库中获取IEnumVariant,我正在尝试使用泛型类将其转换为IEnumerator

存在编译器错误,"运算符不适用于此操作数类型"当试图将IInterface强制转换为泛型类型T. 我在尝试将类型转换为类时遇到过变通方法,但这些不适用于接口。

Rob建议使用Supports似乎有问题,TypeInfo也为参数化类型返回nil。

uses WinApi.ActiveX, Generics.Collections;

type
  TDotNetEnum<T: IInterface> = class(TInterfacedObject, IEnumerator<T>)
  strict private
    FDotNetEnum: IEnumVariant;
    FCurrent: T;
    function MoveNext: Boolean;
    procedure Reset;
    function GetCurrent: TObject;
    function IEnumerator<T>.GetCurrent = GenericGetCurrent;
    function GenericGetCurrent: T;
  public
    constructor Create(const ADotNetObject: OleVariant);

    //// I can get it to work using this constructor
    // constructor Create(const ADotNetObject: OleVariant; const AGUID: TGUID);
  end;

implementation

uses System.Rtti, SysUtils, mscorlib_TLB, ComObj;

constructor TDotNetEnum<T>.Create(const ADotNetObject: OleVariant);
var
  netEnum: IEnumerable;
begin
  netEnum := IUnknown(ADotNetObject) as mscorlib_TLB.IEnumerable;
  FDotNetEnum := netEnum.GetEnumerator();
end;

function TDotNetEnum<T>.GenericGetCurrent: T;
begin
  result := FCurrent;
end;

function TDotNetEnum<T>.GetCurrent: TObject;
begin
  result := nil;
end;

function TDotNetEnum<T>.MoveNext: Boolean;
var
  rgvar: OleVariant;
  fetched: Cardinal;
  ti: TypeInfo;
  guid: TGUID;
begin
  OleCheck(FDotNetEnum.Next(1, rgvar, fetched));
  result := fetched = 1;
  if not result then
    FCurrent := nil
  else
  begin
    FCurrent := IUnknown(rgvar) as T; // <-- Compiler error here
    //// Doesn't work using Supports either
    // ti := TypeInfo(T);  // <-- returns nil
    // guid := GetTypeData(@ti)^.Guid;
    // Supports(IUnknown(rgvar), guid, FCurrent);
  end;
end;

procedure TDotNetEnum<T>.Reset;
begin
  OleCheck(FDotNetEnum.Reset);
end;

我是否遗漏了某些内容以使通用接口类型能够起作用?

我确实有替代构造函数,我可以从中获取guid

TDotNetEnum<IContact>.Create(vContactList, IContact);

工作但理想

TDotNetEnum<IContact>.Create(vContactList); 

没有按&#39;吨

1 个答案:

答案 0 :(得分:6)

使用as转换接口仅对具有GUID的接口有效。编译器在编译泛型类时不能假定T具有GUID,因此它不能接受val as T形式的表达式。

This has been covered before, but in reference to the Supports function,与as运算符具有相同的限制。

解决方案是使用RTTI获取接口的GUID,然后使用它来输入接口值。您可以使用Supports

guid := GetTypeData(TypeInfo(T))^.Guid;
success := Supports(IUnknown(rgvar), guid, FCurrent);
Assert(success);

您也可以直接致电QueryInterface

guid := GetTypeData(TypeInfo(T))^.Guid;
OleCheck(IUnknown(rgvar).QueryInterface(guid, FCurrent));
相关问题