![Неожиданно связь прервалась](http://habrastorage.org/getpro/habr/post_images/a07/2c2/882/a072c2882cffdd65c38cf07d2a81acb6.jpg)
Недавно протокол был оптимизирован, в нем появилась возможность сократить объем передаваемых данных указывая горизонт актуальности. Реализована данная оптимизация с помощью обработки HTTP заголовка IfModifiedSince, однако у объекта HttpWebRequest в PCL не доступного свойство IfModifiedSince. Это не казалось проблемой заголовок был добавлен напрямую в коллекцию заголовков запроса.
request.Headers[HttpRequestHeader.IfModifiedSince] = timeStamp.ToString();
Протестировав решение на WindowsPhone приложении я убедился в его работоспособности, но все юнит тесты транспортного уровня выдали ошибки. Изучив проблему обнаружил, что реализация WebHeaderCollection для платформы Windows, не позволяет напрямую задавать этот заголовок и требует, чтобы разработчики использовали свойство HttpWebRequest.IfModifiedSince которое не доступно в сборках PCL.
Для решения этой я создал метод расширения для класса HttpWebRequest реализующий следующую логику работы:
При первом обращении к методу, пытаемся добавить заголовок в коллекцию заголовков запроса, если это не удается, с помощью отражения ищем у объекта запроса поле IfModifiedSince и создаем и кешируем делегат для установки значения свойства.
При последующих обращениях к методу, используем кэшированный делегат для установки значения заголовка IfModifiedSince.
namespace System.Net { public static class NetExtensions { private static Action<HttpWebRequest, DateTime> _setIfMofifiedSince; public static void SetIfModifiedSince(this HttpWebRequest request, DateTime value) { Guard.NotNull(request); if (_setIfMofifiedSince != null) { _setIfMofifiedSince(request, value); return; } try { request.Headers[HttpRequestHeader.IfModifiedSince] = value.ToString(); return; } // ReSharper disable once EmptyGeneralCatchClause catch { } var property = request.GetType().GetRuntimeProperty("IfModifiedSince"); if (property != null && property.CanWrite) { var method = property.SetMethod; if (method != null) { _setIfMofifiedSince = (Action<HttpWebRequest, DateTime>)method.CreateDelegate(typeof(Action<HttpWebRequest, DateTime>)); } } if (_setIfMofifiedSince == null) { throw new Exception("Unable to set IfModifiedSince"); } _setIfMofifiedSince(request, value); } } }
Используя этот метод расширения код остается простым для чтения и понимания.
request.SetIfModifiedSince(timeStamp);
ссылка на оригинал статьи http://habrahabr.ru/post/219809/
Добавить комментарий