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);
    });
}

一般来说,这段代码应该很容易解释,但这里还有一些事实:

  • 我正在使用延迟优化的 gzip-decoder,它为我提供了方法GetCompressedResponse()(与原始方法基本相同)。
  • 我创建了一些 JSON.net 自定义 JsonConverter 类,以便正确反序列化我的 JSON。这些都相当简单,不会影响性能。
  • 结果类只是我的结果的包装类(包含值和错误字段)
4

1 回答 1

1

我不知道 JSON.net,但是否有一种形式可以采用流或流读取器,而不是强制您先将整个字符串读入内存?如果流可能很大,那将是相当浪费的,尽管如果它们都很小,那将没有什么区别。

有过一个HttpWebrequest.AutomaticDecompression属性可以简化您的代码(公平地说,我自己总是忘记这一点)。

您可以使用该CachePolicy属性让请求使用 IE 缓存,如果您将访问相同的 URI 并且服务器会适当地处理它(适当的 max-age,正确处理条件 GET),这可以节省大量资金。它还允许一些灵活性 - 例如,如果您的使用对新鲜度有很高的要求,您可以使用Revalidate级别,因此您将始终联系服务器,即使 max-age 建议不应该联系服务器,但您仍然可以采取行动适当地在 304 上(呈现给您的代码就好像它是 200,所以您不需要重写所有内容)。

您甚至可以在此之上构建一个对象缓存,您可以在其中使用该IsFromCache方法来了解使用缓存对象是否安全,或者您是否需要重建它,因为它所构建的数据已更改。(实际上这真的很甜蜜,有句名言是关于缓存失效是一个难题,这让我们可以将这个难题的责任转嫁给 HTTP 层,同时让实际的缓存项目存在于 .NET 层中,而不是需要再次反序列化-这是一项工作,因此如果由于数据的性质而不会频繁地缓存命中,请不要这样做,但是在它起作用的地方,它会摇摆不定)。

于 2012-08-14T11:37:21.397 回答