
最近、プロトコルが最適化され、関連の地平線を示す送信データ量を削減することが可能になりました。 この最適化は、IfModifiedSince HTTPヘッダーの処理を使用して実装されていますが、IfModifiedSinceプロパティはPCLのHttpWebRequestオブジェクトでは使用できません。 これは問題ではないようでしたが、ヘッダーはリクエストヘッダーコレクションに直接追加されました。
request.Headers[HttpRequestHeader.IfModifiedSince] = timeStamp.ToString();
WindowsPhoneアプリケーションでソリューションをテストした結果、そのパフォーマンスは確信しましたが、トランスポートレベルのすべてのユニットテストでエラーが発生しました。 この問題を調査した結果、WindowsプラットフォームのWebHeaderCollection実装ではこのヘッダーを直接設定できず、開発者は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);