【问题标题】:Looking for a way to override the GetResponseStream Method of HttpWebResponse寻找一种方法来覆盖 HttpWebResponse 的 GetResponseStream 方法
【发布时间】:2013-09-24 21:24:09
【问题描述】:

我正在寻找一种方法来覆盖 HttpWebResponse 类的 GetResponseStream 方法,以便返回自定义流。基本上我的目标是修改流。不确定这是否可能?这是在与 Web 服务集成的上下文中完成的,我需要从响应流中删除一些内容。有什么想法吗?

【问题讨论】:

  • 不,我不相信这是可能的。很不清楚你的架构是什么——你不能把网络服务包装在一个做正确事情的 API 中吗?你真的需要公开原始流吗?
  • 很遗憾我无法访问网络服务,也无法修改。
  • 不,我说的是在 client 端进行。你真的没有在这里给我们太多的背景......
  • @JonSkeet:实际上,您可以使用 deeply 邪恶的技巧来做到这一点;我尝试过一次并成功了。 (为您的域名注册一个自定义协议处理程序,并调用过时的序列化ctor)
  • @SLaks:我希望 OP 正在寻找不那么邪恶的东西 :)

标签: c# .net web-services stream httpwebresponse


【解决方案1】:

我正在寻找一种方法来覆盖 GetResponseStream 方法 HttpWebResponse 类,以便返回自定义流。

酷。 GetResponseStream 无论如何都是虚拟的,所以继续,覆盖它并返回你想要的任何东西。当然,您必须以这样的方式设计您的代码,这样您就不会使用很少出现的 HttpWebResponse 类的具体实现。因为您通常会从 HttpWebRequest 获得 HttpWebResponse 实例。这就是紧耦合。因此,开始思考如何在代码中抽象出整个 HTTP 内容。我的意思是停止思考 HttpWebRequests。开始考虑代码中的接口和抽象。无论如何,这将拯救你,这将削弱代码不同层之间的耦合并使其可单元测试。

这个答案的重点是,您的代码应该以不依赖于任何 HttpWebRequest 具体类的方式设计。您应该开始考虑将其隐藏在可以在单元测试中轻松模拟的接口抽象后面。

一旦您将 Web 服务调用抽象到接口后面,您就可以在单元测试中轻松地模拟此调用以测试系统的实际行为,而无需依赖测试中的特定类。

【讨论】:

  • 但这需要创建HttpWebResponse 的子类以开始...而实例通常由框架的内部创建(在WebRequest.GetResponse 等中)。你能举一个例子来说明你将如何覆盖它并使用它? (也许有一个我以前从未使用过的插件机制......)
  • 是的,这就是它所需要的。这就是为什么您不应该依赖任何特定的 HTTP 上下文内容,例如代码中的 HttpWebRequests。不,我永远不会覆盖 GetResponseStream 方法。那将是完全疯狂的。我会把对 HttpWebrequest 的全部依赖隐藏在一个接口抽象后面,我可以在单元测试中愉快地模拟它。
【解决方案2】:

您不能轻易覆盖HttpWebResponse 的行为。正如@Jon 在评论中建议的那样,您可以在客户端包装 Web 服务 API,或者,如果您真的想冒险,请更改 request,将其指向一个代理服务器,该代理服务器将根据需要修改流。

不过,这不会是微不足道的。

【讨论】:

    【解决方案3】:

    假设您可以修改调用 GetResponseStream 的代码,适配器模式可能不是一个坏选择。

    类 MyCustomStream : 流 { 流原始流;

      MyCustomStream(Stream originalStream) 
      { this.originalStream = originalStream; }
    
      override int Read(byte [] buffer, int offset, int count) 
      {
          byte [] temp = new byte[count];
          var ret = originalStream.Read(temp, offset, count);
          // modify your buffer if desired
          Array.Copy(buffer, temp);
          return ret;
      }
    
      // implement all the other abstract methods of Stream and just call originalStream 
    

    }

    // 现在替换这样的代码....

    var myStream = request.GetResponseStream();

    // 与....

    var myStream = new MyCustomStream(request.GetResponseStream());

    【讨论】:

    • 这可能不适用于我的情况。它是我通过 .net 使用的 java web 服务,它发送的内容在客户端实际上失败了。我已经从原始代理创建了一个子类并覆盖了 GetWebResponse 方法,在这个方法中我实际上需要更改流的内容,以便在实际解析它时不会引发异常。希望你明白这一点
    • 我不确定...如果您在解析任何内容之前的流级别更改它,对吗?
    • 是的,就是这样。如果我可以在这一点上对其进行更改,它将起作用。接下来的解析不会失败。
    • 所以,如果你像我展示的那样包装流(假设你可以修改调用 GetResponseStream 的代码),你可以在注释点更改缓冲区的内容 "// 如果需要,修改你的缓冲区" 这将从调用者的角度改变流的内容,您将最终控制调用者收到的内容。
    • 在这种情况下,围绕 GetResponseStream 方法的包装方法是 GetWebResponse 方法,我可以覆盖它,因此在某种程度上我可以访问调用 GetResponseStream 方法的代码。但是这里的问题是这里返回的 webresponse 仍然会保留原始流,并且在反序列化/解析时会再次导致异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多