如何实现返回自定义类型TMyType<T>的TVirtualInterface?
实现返回自定义泛型记录的TVirtualInterface
首先,我们得先把你定义的TMyType<T>补全(你之前的代码里第二个隐式转换没写完),然后围绕它构建对应的接口和TVirtualInterface实现。下面是一步步的解决方案:
1. 补全泛型记录的定义
先把TMyType<T>的隐式转换实现完整,确保它能正确和string互转:
TMyType<T> = record private FValue: TValue; public class operator Implicit(A: string): TMyType<T>; class operator Implicit(A: TMyType<T>): string; property Value: TValue read FValue; end; class operator TMyType<T>.Implicit(A: string): TMyType<T>; begin Result.FValue := A; end; class operator TMyType<T>.Implicit(A: TMyType<T>): string; begin Result := A.FValue.AsString; end;
2. 定义对应的泛型接口
TVirtualInterface是用来实现接口的,所以我们需要先定义一个包含返回TMyType<T>方法的泛型接口:
IMyInterface<T> = interface ['{12345678-1234-1234-1234-123456789ABC}'] // 替换成你自己的GUID function GetMyValue: TMyType<T>; end;
3. 创建TVirtualInterface并处理返回值
核心是在TVirtualInterface的Invoke回调里构造TMyType<T>实例,并用TValue正确传递返回值。这里以string作为泛型参数示例:
procedure TestVirtualInterface; var MyVirtualIntf: TVirtualInterface; MyIntf: IMyInterface<string>; begin // 创建TVirtualInterface,绑定到实例化后的接口类型 MyVirtualIntf := TVirtualInterface.Create(TypeInfo(IMyInterface<string>), procedure(Method: TRttiMethod; const Args: TArray<TValue>; out Result: TValue) var MyResult: TMyType<string>; begin // 构造我们需要返回的TMyType<T>实例(这里利用隐式转换赋值) MyResult := 'Hello from Virtual Interface'; // 用TValue.From<T>包装记录类型,赋值给Result Result := TValue.From<TMyType<string>>(MyResult); end); // 转换为目标接口 MyIntf := MyVirtualIntf as IMyInterface<string>; // 测试调用,利用隐式转换直接输出string Writeln(MyIntf.GetMyValue); MyVirtualIntf.Free; end;
4. 泛型场景的封装(可选)
如果需要支持不同的泛型参数类型,可以写一个泛型方法来创建对应的TVirtualInterface:
function CreateMyVirtualInterface<T>: IMyInterface<T>; var VirtualIntf: TVirtualInterface; begin VirtualIntf := TVirtualInterface.Create(TypeInfo(IMyInterface<T>), procedure(Method: TRttiMethod; const Args: TArray<TValue>; out Result: TValue) var MyResult: TMyType<T>; begin // 根据泛型参数T的类型,设置对应的Value if TypeInfo(T) = TypeInfo(Integer) then MyResult.FValue := 123 else if TypeInfo(T) = TypeInfo(string) then MyResult.FValue := 'Generic Test'; // 包装并返回记录 Result := TValue.From<TMyType<T>>(MyResult); end); Result := VirtualIntf as IMyInterface<T>; end;
使用这个泛型方法的示例:
procedure TestGenericVirtualInterface; var IntfStr: IMyInterface<string>; IntfInt: IMyInterface<Integer>; begin IntfStr := CreateMyVirtualInterface<string>; Writeln(IntfStr.GetMyValue); // 输出 "Generic Test" IntfInt := CreateMyVirtualInterface<Integer>; Writeln(IntfInt.GetMyValue.Value.AsInteger); // 输出 123 end;
关键注意事项
- Rtti版本支持:确保你使用的Delphi版本(至少Delphi 2010及以上)支持泛型类型的Rtti识别,否则TVirtualInterface无法正确处理泛型接口和记录。
- 实例化的接口类型:创建TVirtualInterface时必须传入实例化后的泛型接口的TypeInfo(比如
TypeInfo(IMyInterface<string>)),不能直接用开放泛型TypeInfo(IMyInterface<T>)。 - TValue的作用:TValue是Delphi中用来处理动态类型的核心类,它可以正确容纳记录类型(包括泛型记录),所以在Invoke回调中用它来传递返回值是最稳妥的方式。
内容的提问来源于stack exchange,提问作者Passella
相关产品推荐
相关产品推荐

