delphi - 如何将对象转换为接口(interface)(Delphi 中的通用类型约束)

标签 delphi generics delphi-2010

我需要与一系列 .Net Web 服务交互。目前大约有150个。 由于delphi 2010使用Thttprio来实现这一点,我试图在客户端创建一个通用代理,可以调用它来创建适当的soap服务客户端。 有谁知道如何将 httprio 对象转换为通用接口(interface)类型?

谢谢

下面是我尝试使用的代理函数:

class function Web.Proxy<T>(svc: string): T;
var
  HTTPRIO : THTTPRIO;
begin
  HTTPRIO := THTTPRIO.Create(nil);
  HTTPRIO.URL := GetServiceURL(svc);
  Result:= HTTPRIO as T; //<-- Fails with "operator not applicable to this operand type"
  // Result:= T(HTTPRIO); //<-- also fails, but with "invalid typecast"
end;

我的想法是我可以这样调用它:

Web.Proxy<AutmobileServiceSoap>('svc.asmx').GetAutomobile(125);

WSDL 导入的 AutmobileServiceSoap 定义如下:

AutmobileServiceSoap = interface(IInvokable)

所有 wsdl 导入都有一个以类似方式返回 httprio 对象的函数:

function GetAutomobileServiceSoap(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): AutomobileServiceSoap;
const
  defWSDL = 'http://localhost:8732/Cars.Server/Data/AutomobileService.asmx?WSDL';
  defURL  = 'http://localhost:8732/Cars.Server/Data/AutomobileService.asmx';
  defSvc  = 'AutomobileService';
  defPrt  = 'AutomobileServiceSoap12';
var
  RIO: THTTPRIO;
begin
  Result := nil;
  if (Addr = '') then
  begin
    if UseWSDL then
      Addr := defWSDL
    else
      Addr := defURL;
  end;
  if HTTPRIO = nil then
    RIO := THTTPRIO.Create(nil)
  else
    RIO := HTTPRIO;
  try
    Result := (RIO as AutomobileServiceSoap);
    if UseWSDL then
    begin
      RIO.WSDLLocation := Addr;
      RIO.Service := defSvc;
      RIO.Port := defPrt;
    end else
      RIO.URL := Addr;
  finally
    if (Result = nil) and (HTTPRIO = nil) then
      RIO.Free;
  end;
end;

最佳答案

您必须使用 RTTI 来获取接口(interface)的 GUID

type
  Web = class
    class function Proxy<T: IInterface>(svc: string): T;
  end;

class function Web.Proxy<T>(svc: string): T;
var
  HTTPRIO: THTTPRIO;
  data: PTypeData;
begin
  HTTPRIO := THTTPRIO.Create(nil);
  HTTPRIO.URL := GetServiceURL(svc);
  data := GetTypeData(TypeInfo(T));
  if ifHasGuid in data.IntfFlags then
  begin
    HTTPRIO.QueryInterface(data.Guid, Result);
  end;
end;

如果您指定 IInterface 约束,您可以确保 T 始终是一个接口(interface)(否则您还必须检查 TypeInfo 的 TypeKind)。

关于delphi - 如何将对象转换为接口(interface)(Delphi 中的通用类型约束),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17426624/

相关文章:

c#-4.0 - 在委托(delegate)、Func 或 Action C# 中推广 Dapper 查询

快速修改结构的通用属性

德尔福的OTA : is there a way to get active configuration while building (D2010)?

Delphi 2010 及早期编译器

delphi - 如何让同一个按钮每次点击时运行不同的代码?

Delphi Firemonkey - 在运行时加载样式

delphi - T触摸键盘 : send keystroke to other program?

multithreading - TRTTIContext多线程问题

delphi - TNetHttpClient 自定义超时

Java 原始类型声明