C # HttpWebRequest против WebRequest

112

Я видел этот фрагмент кода:

var request = (HttpWebRequest) WebRequest.Create("http://www.google.com");

Зачем нужно кастовать (HttpWebRequest)? Почему бы просто не использовать HttpWebRequest.Create? А почему делает HttpWebRequest.Createа WebRequest, а не а HttpWebRequest?

Неизвестно
источник
связанные с сообщениями: stackoverflow.com/q/8209781/274502
cregox

Ответы:

134

CreateМетод является статическим, и существует только WebRequest. Вызов его как HttpWebRequest.Createможет выглядеть иначе, но на самом деле он скомпилирован до вызова WebRequest.Create. Только кажется, что он включен HttpWebRequestиз-за наследования.

CreateМетод внутренне использует шаблон фабрики , чтобы сделать фактическое создание объектов, основанный на Uriвы передаете в него. Фактически вы можете получить обратно другие объекты, такие как FtpWebRequestили FileWebRequest, в зависимости от Uri.

Дэвид Венгер
источник
3
Это правильно. Было бы неплохо, если бы существовал способ получить HttpWebRequest из HttpWebRequest.Create или чего-то вроде HttpWebRequest.CreateHttp без преобразования. Первым будет что-то вроде общедоступного нового статического HttpWebRequest Create (строковый URL). В любом случае, если URL-адрес не был HTTP (-ами), он должен просто выбросить какое-то исключение InvalidArgumentException.
Мэтью Флашен,
4
Прекрасное объяснение очень странного дизайнерского решения (осмелюсь ли сказать, что нет?) Создателей .NET.
Эй Джей Кеннеди,
2
@IJKennedy Полностью согласен, очень странное, нелогичное и непрактичное дизайнерское решение.
Aidiakapi 08
8
HttpWebRequest.CreateHttp действительно существует и создает экземпляр HttpWebRequest.
Питер Майнл
4
@Bobson WebRequest.CreateHttpнаходится в 4.5
Марк
31

WebRequest- это абстрактный класс, который имеет фабричный метод, Createкоторый, в зависимости от переданного URL-адреса, создает экземпляр конкретного подкласса. Нужны вы или хотите, HttpWebRequest httpreq = (HttpWebRequest)WebRequest.Create(strUrl);а не WebRequest req = WebRequest.Create(strUrl);зависит от ваших потребностей и от того, какие URL-адреса вы передаете.

Если вы передаете только URL-адреса HTTP:, тогда предыдущий код позволяет вам получить доступ к свойствам и методам, которые подкласс HttpWebRequestреализует в дополнение к тем, которые определены в базовом классе WebRequest. Но если вы передали URL-адрес FTP :, попытка преобразования HttpWebRequestзавершится неудачей.

Последний является общим и не даст сбоев ни для одного из типов поддерживаемых URL-адресов, но, конечно, без преобразования в какой-либо подкласс вы можете получить доступ только к свойствам и методам, которые определяет базовый класс.

- через Мартина Хоннена

Орхан Чинар
источник
12

Приведение необходимо только тогда, когда вам нужен доступ к членам, уникальным для HttpWebRequest. Идея состоит в том, что если свойств / методов, поддерживаемых в WebRequest, достаточно, то вы можете написать приложение, которое будет работать со многими типами протоколов запроса / ответа. В этом случае URI может быть чем-то заданным пользователем с использованием любого протокола, поддерживаемого подключаемыми протоколами. Новые протоколы могут поддерживаться даже без изменения исходного программного обеспечения.

Если вашему приложению требуется больший контроль над функциями, специфичными для конкретного протокола, вы можете ограничить requestUri своей поддерживаемой схемой (ами) и передать WebRequest соответствующему подклассу, зависящему от протокола. Это ограничивает протоколы, поддерживаемые вашим приложением, но позволяет настраивать специфические для протокола функции.

Кевин
источник