【问题标题】:How can I cast an object as an interface which is a generic type constraint in Delphi如何将对象转换为在 Delphi 中作为泛型类型约束的接口
【发布时间】:2013-07-02 13:14:24
【问题描述】:

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

谢谢

下面是我尝试使用的代理功能:

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;

【问题讨论】:

    标签: delphi generics delphi-2010


    【解决方案1】:

    你必须使用 RTTI 来获取接口的 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 始终是一个接口(否则您还必须检查 TypeInfo 的 TypeKind)。

    【讨论】:

    • +1,实际上QueryInterface需要IInterface,否则IUnknown就足够了:)
    • @whosrdaddy 实际上,您不需要约束就可以编译,但是有了约束,您可以安全地仅将其与接口一起使用,这些接口是唯一有意义的类型。我认为您甚至可以摆脱 has guid 检查,否则它无论如何都不适用于 THTTPRio。
    【解决方案2】:

    因为T 可以是任何东西,你必须让Delphi 清楚T 将是一个接口。 由于所有接口都继承自IUnknown,所以可以这样写:

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

    【讨论】:

    • 谢谢,但是有了这个更改,虽然现在使用 T(HttpRIO) 进行转换可以编译,但是当我调用它时会遇到访问冲突。
    • 我害怕那个。可以使用rtti吗?
    • 看来你有答案了:)
    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-16
    • 2010-11-08
    相关资源
    最近更新 更多