2010-12-01 42 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之外,这是不可用的)。

相关问题