代码之家  ›  专栏  ›  技术社区  ›  William Leader

delphiweb服务生成的WSDL中不包括可迁移的子代父成员

  •  1
  • William Leader  · 技术社区  · 14 年前

    TBaseRequest = Class(TRemotable)
      private
        FUsername: string;
        FPassword: string;
      published
        Property Username: String read FUsername write FUsername;
        Property Password: String read FPassword write FPassword;
    End;
    
    TBaseResponse = Class(TRemotable)
      private
        FStatusMessage: string;
        FStatusCode: integer;
      published
        Property StatusMessage: string read FStatusMessage write FStatusMessage;
        Property StatusCode: integer read FStatusCode write FStatusCode;
    End;
    
    TSepecialRequest = class(TBaseRequest)
    private
      FExtraParam: string;
    published
      Property ExtraParam: String read FExtraParam write FExtraParam;
    end;
    
    TSpecialResponse = class(TBaseResponse)
    private
      FExtraResult: string;
    published
      Property ExtraResult: String read FExtraResultwrite FExtraResult;
    end;
    

    现在,我还在该Web服务的接口中定义了以下函数:

    function SpecialMethod(request:TSepecialRequest): TSpecialResponse;
    

      <xs:complexType name="TSpecialRequest">
        <xs:complexContent>
          <xs:extension base="TBaseRequest">
            <xs:sequence>
              <xs:element name="ExtraParam" type="xs:string"/>
            </xs:sequence>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>
      <xs:complexType name="TSpecialResponse">
        <xs:complexContent>
          <xs:extension base="TBaseResponse">
            <xs:sequence>
              <xs:element name="ExtraResult" type="xs:string"/>
            </xs:sequence>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>
    

    WSDL中的这个模式片段表明,TSpecials是TBase类的扩展,除了模式中不包括TBase类的描述之外,其他都很好。我希望也会有这样一个部分,但它是缺失的:

      <xs:complexType name="TBaseRequest">
        <xs:sequence>
          <xs:element name="Username" type="xs:string"/>
          <xs:element name="Password" type="xs:string"/>
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="TBaseResponse">
        <xs:sequence>
          <xs:element name="StatusMessage" type="xs:string"/>
          <xs:element name="StatusCode" type="xs:int"/>
        </xs:sequence>
      </xs:complexType>
    

    但是,生成的WSDL中缺少此模式片段。这意味着任何试图使用此服务的客户端都将无法正确生成请求或解释响应。例如,如果我尝试在Delphi 2009中将生成的WSDL加载到WSDL导入器中,我会得到以下类:

    TSpecialRequest = class(TRemotable)
    private
      FExtraParam: WideString;
    published
      property ExtraParam: WideString read FExtraParam write FExtraParam;
    end;
    
    TSpecialResponse = class(TRemotable)
    private
      FStatusMessage: WideString;
      FStatusCode: Integer;
    published
      property StatusMessag: WideString read FStatusMessage write FStatusMessage;
      property StatusCode: Integer read FStatusCode write FStatusCode;
    end;
    

    有人知道为什么会这样吗?或者我能做些什么?

    2 回复  |  直到 14 年前
        1
  •  1
  •   William Leader    14 年前

    我想我不会得到答案,但我已经找到了一个解决办法。我对它不太满意,但它让我通过了这个问题。通过使用对象组合而不是继承,可以避免上述症状。此代码的功能与预期相同,但使用起来不太简单。我想我会想在我的实现中提出某种消息工厂,但这已经偏离主题了。

    此解决方案可以通过以下代码来说明:

    TBaseRequest = Class(TRemotable)
      private
        FUsername: string;
        FPassword: string;
      published
        Property Username: String read FUsername write FUsername;
        Property Password: String read FPassword write FPassword;
    end;
    
    TSepecialRequest = class(TRemotable)
    private
      FExtraParam: string;
      FBaseRequest: TBaseRequest;
    published
      Property ExtraParam: String read FExtraParam write FExtraParam;
      Property BaseRequest: TBaseRequest read FBaseRequest write FBaseRequest;
    end;
    
        2
  •  1
  •   Jessie Potts    13 年前

    Delphi只为web服务接口中直接引用的类生成模式。理想情况下,它应该包含返回到TRemotable的基类,但事实并非如此。

    不过,我发现,如果在参数列表中使用基类向接口添加一个伪方法,Delphi将生成缺少的定义。例如:

    procedure BaseClasses(BaseRequest: TBaseRequest; BaseResponse: TBaseResponse); stdcall;
    

    我知道这个回答对你来说有点晚,但也许对以后的其他人会有用。