Создание WebRequestFactory на Windows Phone 7 - PullRequest
2 голосов
/ 21 мая 2011

Я пытаюсь создать основанный на Rx WebRequestFactory для использования любого универсального API.

Я получил полусортированный базовый запрос GET

public static IObservable<T> GetData<T>(Uri uri, Func<string, T> generator)
{
    System.Diagnostics.Debug.WriteLine(uri);
    return (from request in Observable.Return(CreateWebRequest(uri))
            from response in Observable.FromAsyncPattern<WebResponse>(request.BeginGetResponse, request.EndGetResponse)()
            select generator(new StreamReader(response.GetResponseStream()).ReadToEnd())).ObserveOnDispatcher();
}

private static WebRequest CreateWebRequest(Uri uri)
{
    var ret = (HttpWebRequest)WebRequest.Create(uri);
    ret.AllowReadStreamBuffering = false;
    return ret;
}

Что работает хорошо, но я не уверен, как обработка исключений осуществляется в Rx, это делается только в методе Subscribe ()? То есть Подписаться (onNext: response => handleResponse (response), onError: error => handleError (error) Или я могу поймать его раньше?

Мне также трудно получить POST-версию GetData, в настоящее время у меня есть:

public static IObservable<T> PostData<T>(Uri uri, Func<string, T> generator, String postData)
{
    System.Diagnostics.Debug.WriteLine(uri);
    byte[] buffer = Encoding.UTF8.GetBytes(postData);

    var request = CreatePOSTWebRequest(uri);

    var obs1 = Observable.FromAsyncPattern<WebResponse>(request.BeginGetResponse, request.EndGetResponse)();

    return null;
}

private static WebRequest CreatePOSTWebRequest(Uri uri)
{
    var ret = (HttpWebRequest)WebRequest.Create(uri);
    ret.Method = "POST";
    ret.AllowReadStreamBuffering = false;
    return ret;
}

Но я понятия не имею, как подключить отправку события данных POST, а затем получить ответ сервера.

Я впервые использую Async HTTPRequests, поэтому любая помощь будет высоко ценится

Редактировать: (Надеюсь, это рекомендуемый способ переполнения стека для добавления к моему вопросу)

Я думаю, что решил это, используя вместо этого WebClient:

public static IObservable<T> PostData<T>(Uri uri, Func<string, T> generator, String postData)
{
    System.Diagnostics.Debug.WriteLine(uri);
    WebClient wc = CreatePostWebClient(uri, postData);
    return (from e in Observable.FromEvent<UploadStringCompletedEventArgs>(wc, "UploadStringCompleted")
            select generator(e.EventArgs.Result)).ObserveOnDispatcher();

}

public static WebClient CreatePostWebClient(Uri uri, string postData)
{
    var wc = new WebClient();
    wc.AllowReadStreamBuffering = false;
    wc.UploadStringAsync(uri, postData);
    return wc;
}

Но я немного обеспокоен тем, что это дает мне состояние гонки, так как я начинаю загрузку, прежде чем наблюдаю за ответом.

1 Ответ

2 голосов
/ 21 мая 2011

Вы правы, обработка ошибок выполняется путем отправки сообщения OnError по конвейеру и отписки от источника. Есть операторы, которые могут изменить это поведение, например Catch, которые могут предоставить новую последовательность для использования вместо нее (например, возвращая значение по умолчанию, используя Observable.Return).

Что касается публикации данных, это не должно быть слишком сложно, если вы не планируете фактически асинхронную буферизацию данных запроса, чтобы не блокировать клиента (в этом случае он становится значительно более сложным). Пока это просто почтовые данные, они должны выглядеть примерно так:

return (from request in Observable.Return(CreateWebRequest(uri))
        from requestStream in Observable.FromAsyncPattern<WebResponse>(
                                  request.BeginGetRequest, request.EndGetRequest)()
        from response in PostAndGetResponse(request, requestStream)
        select generator(new StreamReader(response.GetResponseStream()).ReadToEnd())
       ).ObserveOnDispatcher();

private IObservable<WebResponse> PostAndGetResponse(
    WebRequest request, Stream requestStream)
{
    // Write data to requestStream

    return Observable.FromAsyncPattern<WebResponse>(
        request.BeginGetResponse, request.EndGetResponse)()
}
...