You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现返回自定义类型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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:55:09