gpt4 book ai didi

delphi - 将泛型类转换为 Delphi 接口(interface)

转载 作者:行者123 更新时间:2023-12-03 15:48:13 24 4
gpt4 key购买 nike

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

尝试将 IInterface 转换为泛型类型 T 时出现编译器错误“运算符不适用于此操作数类型”当尝试将类型转换为类时,我已经看到了解决方法,但这些方法不适用于接口(interface)。

按照 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;

为了让通用接口(interface)类型正常工作,我是否遗漏了一些东西?

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

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

可行但理想

TDotNetEnum<IContact>.Create(vContactList); 

没有

最佳答案

使用as来转换接口(interface)仅对具有GUID的接口(interface)有效。编译器在编译泛型类时无法假设 T 有 GUID,因此它无法接受 val as T 形式的表达式。

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

解决方案是使用 RTTI 获取接口(interface)的 GUID,然后使用它来对接口(interface)值进行类型转换。您可以使用支持:

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));

关于delphi - 将泛型类转换为 Delphi 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25084414/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com