我需要与一系列.Net网络服务进行互动。目前大约有150个。 由于delphi 2010使用Thttprio来实现这一点,我试图在客户端创建一个通用代理,可以调用它来创建适当的soap服务客户端。 有谁知道如何将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;
答案 0 :(得分:5)
您必须使用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 :(得分:2)
由于T
可以是任何内容,因此您必须向Delphi明确T
将是一个接口。
由于所有接口都继承自IUnknown
,因此您可以这样写:
Web = class
class function Proxy<T :IUnknown>(svc : string) : T;
end;