2010-12-01 51 views
2

我試圖在單個方法中通過Reactive接口IObservable返回HttpWebRequest POST方法的結果。我已經成功地使用下面的代碼爲GET方法做到這一點:是否有可能通過IObservable接口返回HttpWebRequest POST方法的結果

var request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(url); 
    request.Method = method; 
    request.Accept = GetHttpType(); 
    request.CookieContainer = new CookieContainer(); 

    return Observable.FromAsyncPattern(request.BeginGetResponse, ar => ProcessResponse(method, ar, request))() 
        .Select(r => r); 

但我不確定如何鏈連同所需要的響應流的讀取寫入請求流的異步觀察者用於HTTP POST操作。如何將以下變量obs1 & obs2連接在一起,以便我可以返回obs2?

var request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(url); 
var type = GetHttpType(); 
request.Method = method; 
request.Accept = type; 
request.ContentType = type; 
request.CookieContainer = new CookieContainer(); 

var data = Serialize(requestResource); 

var obs1 = Observable.FromAsyncPattern(request.BeginGetRequestStream, ar1 => ProcessRequest(method, data, ar1, request)) 

var obs2 = Observable.FromAsyncPattern(request.BeginGetResponse, ar2 => ProcessResponse(method, ar2, request))(); 

// How do I connect obs1 And obs2 together... 

return obs2; 

我還以爲下面應該工作,但「ProcessResponse」方法不會被調用,沒有人知道爲什麼嗎?

var obs1 = Observable.FromAsyncPattern(request.BeginGetRequestStream, ar1 => ProcessRequest(method, data, ar1, request))(); 
var obs2 = Observable.FromAsyncPattern(request.BeginGetResponse, ar2 => ProcessResponse(method, ar2, request)); 

return obs1.SelectMany(a => obs2(), (a, b) => b); 

回答

-1

obs1.Concat(obs2)也許?

+0

他們不是相同類型,所以我不能連接,謝謝 – AwkwardCoder 2010-12-01 13:33:57

+0

對不起,我當時沒有太多關注。我會盡量不從'屁股'從現在開始:) – rawpower 2010-12-01 21:04:37

2

FromAsyncPattern正在期待BeginAction和EndAction方法作爲參數。我知道你在尋找的是這樣的:

HttpWebRequest httpRequest = 
    (HttpWebRequest)HttpWebRequest.Create("http://www.stackoverflow.com"); 

httpRequest.Method = "POST"; 

var requestAsync = Observable.FromAsyncPattern<Stream>(
    httpRequest.BeginGetRequestStream, httpRequest.EndGetRequestStream); 

var responseAsync = Observable.FromAsyncPattern<WebResponse>(
    httpRequest.BeginGetResponse, httpRequest.EndGetResponse); 

requestAsync() 
    .SelectMany(requestStream => 
    { 
     // requestStream.Write 

     return responseAsync(); 
    }) 
    .Subscribe(webResponse => 
    { 
     // complete 
    }); 

讓我知道,如果你寫的請求流是異步的,我可以相應地更新樣本。

+0

我有類似的東西,但如果你有多個訂閱者的觀察,那麼'SelectMany'將觸發多次,因此試圖寫入流多不是所需行爲的時間 - 理想情況下寫入請求流只發生一次... – AwkwardCoder 2010-12-01 22:56:34

1

好的,我現在明白了。首先是代碼,然後解釋:

byte[] buffer1 = Encoding.UTF8.GetBytes(data); // assume post data is utf-8 encoded 

var obs1 = Observable.FromAsyncPattern(request.BeginGetRequestStream, ar1 => request.EndGetRequestStream(ar1)); 

return from stream in obs1() 
     let obs2 = Observable.FromAsyncPattern((ac, state) => stream.BeginWrite(buffer1, 0, buffer1.Length, ac, state), ar2 => stream.EndWrite(ar2)) 
     from _ in obs2() 
     let obs3 = Observable.FromAsyncPattern(request.BeginGetResponse, ar2 => request.EndGetResponse(ar2)) 
     from response in obs3() 
     select response; 

你在SelectMany的正確軌道上,但我發現常規的LINQ語法更具可讀性。我還通過異步發佈來改進您的示例,即以異步方式寫入上傳流。基本上第一個from爲我們提供了一個用於第一個let中的異步帖子的流,第三個將忽略上傳結果(因此命名爲變量'_'),最後從最後一個簡單地訂閱結果獲得迴應。

我必須承認,我發現這個例子延伸了Observable的概念。我想你會通過使用Task s得到更好的結果和更具可讀性的代碼,並且可能使用C#5中的新異步支持甚至更好的結果(但除了CPT之外,這是不可用的)。

相關問題