
複数のプラットフォーム用のアプリケーションを開発しています。PCLを使用してプラットフォームに依存しない部分全体を作成し、コンポーネントの最大限の再利用を実現しようとしています。 サーバーとの通信には、HttpWebRequestクラスが使用され、トランスポートレベルで必要なすべての機能が実装されます。
最近、プロトコルが最適化され、関連の地平線を示す送信データ量を削減することが可能になりました。 この最適化は、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; }
この拡張メソッドを使用すると、コードは読みやすく理解しやすいままです。
request.SetIfModifiedSince(timeStamp);