Безопасное использование заголовка HTTP IfModifiedSince в PCL библиотеках

Неожиданно связь прервалась Мы разрабатываем приложение под несколько платформ, всю платформо независимую часть создаем с помощью PCL, стараясь добиться максимального уровня пере использования компонентов. Для коммуникаций с сервером используется класс HttpWebRequest который реализует всю необходимую от транспортного уровня функциональность.Недавно протокол был оптимизирован, в нем появилась возможность сократить объем передаваемых данных указывая горизонт актуальности. Реализована данная оптимизация с помощью обработки 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 _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)method.CreateDelegate (typeof (Action)); } }

if (_setIfMofifiedSince == null) { throw new Exception («Unable to set IfModifiedSince»); }

_setIfMofifiedSince (request, value); } } } Используя этот метод расширения код остается простым для чтения и понимания.

request.SetIfModifiedSince (timeStamp);

© Habrahabr.ru