C# HttpWebRequest与WebRequest的区别

116

我看到了这段代码:

var request = (HttpWebRequest) WebRequest.Create("http://www.google.com");
为什么需要进行强制类型转换为 (HttpWebRequest),而不直接使用 HttpWebRequest.Create?为什么 HttpWebRequest.Create 会创建一个 WebRequest 而不是一个 HttpWebRequest?

您为什么需要将对象强制类型转换为 (HttpWebRequest),而不直接使用 HttpWebRequest.Create 呢?并且为什么 HttpWebRequest.Create 创建的是 WebRequest 而不是 HttpWebRequest 呢?


与帖子相关:https://dev59.com/4msy5IYBdhLWcg3w8Slc - cregox
4个回答

137

Create 方法是静态的,仅存在于 WebRequest 上。调用它作为 HttpWebRequest.Create 看起来可能不同,但实际上被编译成调用 WebRequest.Create。它之所以仅出现在 HttpWebRequest 上,是因为继承的原因。

Create 方法在内部使用工厂模式根据传递给它的 Uri 实际创建对象。你实际上可以获取其他对象,如 FtpWebRequestFileWebRequest,这取决于 Uri


3
没问题。如果能够在不需要转换类型的情况下从HttpWebRequest.Create或类似的HttpWebRequest.CreateHttp获得HttpWebRequest会很方便。第一个方法可能是这样的:public new static HttpWebRequest Create(string url)。无论哪种方式,如果url不是HTTP(s),它应该抛出一些InvalidArgumentException。 - Matthew Flaschen
4
.NET 创造者的一个非常奇怪(也许可以说是错误?)的设计决策有一个很好的解释。 - I. J. Kennedy
2
@I.J.Kennedy 我完全同意,这是一个非常奇怪、不合逻辑和不切实际的设计决策。 - Aidiakapi
8
HttpWebRequest.CreateHttp 存在并且可以创建一个 HttpWebRequest 实例。 - Peter Meinl
5
@Bobson WebRequest.CreateHttp 在 .NET Framework 4.5 中引入。 - Mark
显示剩余2条评论

34

WebRequest 是一个抽象类,它有一个名为Create的工厂方法,根据传入的URL创建具体子类的实例。使用HttpWebRequest httpreq = (HttpWebRequest)WebRequest.Create(strUrl);还是WebRequest req = WebRequest.Create(strUrl);取决于您的需求以及传入的URL类型。

如果只传输HTTP: URL,则前者的代码允许您访问子类HttpWebRequest中定义的属性和方法,但也可以访问基类WebRequest中定义的属性和方法。但如果传入FTP: URL,则尝试将其转换为HttpWebRequest将失败。

后者是通用的且不会在任何支持的URL类型上失败,但是当然,如果没有向任何子类强制转换,则只能访问基类定义的属性和方法。

-- via Martin Honnen


12

只有在需要访问 HttpWebRequest 特有成员时才需要进行强制类型转换。这种想法是,如果 WebRequest 上支持的属性/方法足够使用,则可以编写适用于许多请求/响应协议类型的应用程序。在这种情况下,URI 可以是使用可插拔协议支持的任何协议由用户提供的内容。甚至可以在不更改原始软件的情况下支持新协议。

如果您的应用程序需要对特定协议的特定功能进行更多控制,则可以将 requestUri 限制为您支持的方案,并将 WebRequest 强制转换为适当的协议特定子类。这会限制您的应用程序所支持的协议,但使您能够调整协议特定功能。


0

我们将使用WebRequest方法,因为它可以作为通用方法透明地从以下位置检索文件:

  • Web服务器,
  • FTP服务器和
  • 文件服务器

所以

var httpRequest = WebRequest.Create("http://somedomain.com");       // return an instance of type(HttpWebRequest)
var ftpRequest = WebRequest.Create("ftp://ftp.somedomain.com");     // return an instance of type(FtpWebRequest)
var fileRequest = WebRequest.Create("file://files.somedomain.com"); // return an instance of type(FileWebRequest)

所有三个方法(HttpWebRequest、FtpWebRequest、FileWebRequest)的“返回类型”都继承自基类WebRequest,该基类是“WebRequest.Create(string)”方法的返回类型。 现在要实例化哪个“子类”是使用协议前缀(http:,https:,ftp:,file:)来确定的。
因此,您传递给Create方法的任何带有这四个前缀之一的URI字符串将由“WebRequest”基类透明地处理,因此您甚至不必知道具体返回了哪个“子类”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接