我从一个.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);
不会
GetLastError()
报告错误,因此使用RaiseLastOSError()
是错误的。应该使用OleCheck()
,例如:OleCheck(FDotNetEnum.Next(1, rgvar, fetched));
和OleCheck(FDotNetEnum.Reset);
。 - Remy Lebeau