1

REST サービスと対話するために、独自の実装を作成しました (非常に簡単です)。GET リクエストのコードは以下にあります。ただし、リクエストのパフォーマンスを低下させる明らかな落とし穴がコードにあるかどうかを知りたいです。彼らは今のところまともに働いていますが、もっと良い仕事ができたのではないかと感じています。

どんなフィードバックでも大歓迎です!

public static void Get<T>(string url, Action<Result<T>> callback, NetworkCredential credentials = null, JsonConverter converter = null)
{
    // Checks for no internet
    if (!NetworkInterface.GetIsNetworkAvailable())
    {
        callback(new Result<T>(new NoInternetException()));
        return;
    }

    // Sets up the web request for the given URL (REST-call)
    var webRequest = WebRequest.Create(url) as HttpWebRequest;

    // Makes sure we'll accept gzip encoded responses
    webRequest.Headers[HttpRequestHeader.AcceptEncoding] = "gzip";

    // If any credentials were sent, attach them to request
    webRequest.Credentials = credentials;

    // Queues things up in a thread pool
    ThreadPool.QueueUserWorkItem((object ignore) =>
    {
        // Starts receiving the response
        webRequest.BeginGetCompressedResponse(responseResult =>
        {
            try
            {
                // Fetches the response
                var response = (HttpWebResponse)webRequest.EndGetResponse(responseResult);

                // If there _is_ a response, convert the JSON
                if (response != null)
                {
                    // Gives us a standard variable to put stuff into
                    var result = default(T);

                    // Creates the settings-object to insert all custom converters into
                    var settings = new JsonSerializerSettings();

                    // Inserts the relevant converters
                    if (converter != null)
                    {
                        if (converter is JsonMovieConverter)
                        {
                            settings.Converters.Add(new JsonMovieListConverter());
                        }
                        settings.Converters.Add(converter);
                    }

                    // Depending on whether or not something is encoded as GZIP - deserialize from JSON in the correct way
                    if (response.Headers[HttpRequestHeader.ContentEncoding] == "gzip")
                    {
                        var gzipStream = response.GetCompressedResponseStream();

                        result = JsonConvert.DeserializeObject<T>(new StreamReader(gzipStream).ReadToEnd(), settings);
                    }
                    else
                    {
                        result = JsonConvert.DeserializeObject<T>(new StreamReader(response.GetResponseStream()).ReadToEnd(), settings);
                    }

                    // Close the response
                    response.Close();

                    // Launch callback
                    callback(new Result<T>(result));
                }
            }
            catch (Exception ex) // Deals with errors
            {
                if (ex is WebException && ((WebException)ex).Response != null && ((HttpWebResponse)((WebException)ex).Response).StatusCode == HttpStatusCode.Unauthorized)
                {
                    callback(new Result<T>(new UnauthorizedException()));
                }
                else
                {
                    callback(new Result<T>(ex));
                }
            }
        }, webRequest);
    });
}

一般に、このコードは一目瞭然ですが、さらにいくつかの事実があります。

  • メソッドを提供するDelayの最適化された gzip-decoderを使用していますGetCompressedResponse()(基本的には元のメソッドと同じです)。
  • JSON を正しく逆シリアル化するために、いくつかの JSON.net カスタム JsonConverter クラスを作成しました。これらはかなり単純で、パフォーマンスには影響しません。
  • Result-class は、単に結果のラッパー クラスです (Value フィールドと Error フィールドを含みます)。
4

1 に答える 1

1

JSON.net はわかりませんが、最初に文字列全体を強制的にメモリに読み込ませるのではなく、ストリームまたはストリームリーダーを使用するフォームはありますか? ストリームがすべて小さい場合は違いはありませんが、ストリームが大きくなる可能性がある場合はかなり無駄です。

2.0 以降、コードを簡素化できるプロパティがありましたHttpWebrequest.AutomaticDecompression(公平を期すために、私はいつもそれを忘れています)。

プロパティを使用CachePolicyして、リクエストに IE キャッシュを使用させることができます。これは、同じ URI にヒットし、サーバーがそれを適切に処理する場合 (適切な max-age、条件付き GET の正しい処理)、大きな節約になる可能性があります。また、ある程度の柔軟性も提供します。たとえば、使用に鮮度に対する高い要件がある場合は、Revalidateレベルを使用できるため、max-age がサーバーに接続すべきではないことを示唆している場合でも、常にサーバーに接続できますが、それでも行動することができます304 で適切に (200 であるかのようにコードに表示されるため、すべてを書き直す必要はありません)。

この上にオブジェクト キャッシュを構築することもできます。IsFromCacheメソッドを使用して、キャッシュされたオブジェクトを安全に使用できるかどうか、または構築元のデータが変更されたために再構築する必要があるかどうかを確認できます。(これは実に素晴らしいことです。キャッシュの無効化は困難な問題であるという有名な行があります。これにより、実際のキャッシュされたアイテムは .NET レイヤーではなく、.NET レイヤーに存在する一方で、そのハード ビットの負担を HTTP レイヤーに渡すことができます。再度デシリアライズする必要があります - ちょっとした作業なので、データの性質上キャッシュ ヒットが頻繁に発生しない場合は実行しないでください。

于 2012-08-14T11:37:21.397 に答える