使用RX方式模拟DoubanFm的登陆

WP7下的Get Post都是异步的

关于RX

http://www.cnblogs.com/yangecnu/archive/2012/11/03/Introducting_ReactiveExtensions.html

我初步理解的Rx,是观察者模式的一种实现

Url很简单,先来看看URL

  • URL: http://www.douban.com/j/app/login

  • Method: POST

  • Arguments:

    • app_nameradio_desktop_win

    • version100

    • email用户帐号

    • password明文密码

  • Header: Content-Type: application/x-www-form-urlencoded

  • Response ( application/json )

在WP7下的Post过程大致如下(Get过程相对简单,只需要2步):

第一步:

 1     public void PostMethod(string Url,string Postdata)

 2         {

 3 

 4             HttpWebRequest request;

 5             request = (HttpWebRequest)WebRequest.Create(new Uri(Url));

 6             request.Method = "POST";

 7             request.ContentType = "application/x-www-form-urlencoded";

 8             request.BeginGetRequestStream(new AsyncCallback(RequestCallback), request);10             _postdata = Postdata;

11         }

第二步:

 1    private void RequestCallback(IAsyncResult asyncResult)

 2         {

 3            HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;

 4             UTF8Encoding encoding = new UTF8Encoding();

 5             Stream _body = request.EndGetRequestStream(asyncResult);

 6             byte[] formBytes = encoding.GetBytes(_postdata);//这是通过post方式传的

 7             _body.Write(formBytes, 0, formBytes.Length);

 8             _body.Close();

 9             request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);

10 

11          }

第三步:

 1      private void ResponseCallback(IAsyncResult asyncResult)

 2         {

 3             HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;

 4                

 5                     WebResponse httpwebresponse = request.EndGetResponse(asyncResult);

 6                     Stream stream=   httpwebresponse.GetResponseStream();

 7                     StreamReader reader = new StreamReader(stream);

 8                     string result=reader.ReadToEnd();

 9                  

10             // Deployment.Current.Dispatcher.BeginInvoke(_postret, result);

11             

12         }

刚学习了Rx,想看看如果用Rx应该怎么做

先来回顾下Rx 如下

  public interface IObservable<T>  {  IDisposable Subscribe(IObserver<T> observer); } 

1    public interface IObserver<T>

2     {

3         void OnCompleted();

4         void OnError(Exception exception);

5         void OnNext(T value);

6     }

在我的System.Reactive.Linq的Observable静态类下,定义了了IObservable<T>的很多扩展方法,

    public static IObservable<TResult> Select<TSource, TResult>(this IObservable<TSource> source, Func<TSource, TResult> selector)
  public static IObservable<TResult> SelectMany<TSource, TResult>(this IObservable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)

这些扩展方法反映了我们可以像Linq一样获得一个IObservable<T>

下面是获得一个IObservable<T>的最简单的方法

  public static IObservable<TResult> Return<TResult>(TResult value)

用这个方法得到的IObservable<T>后就可以注册了,在我的System.Reactive.Core.dll,System命名空间下的ObservableExtensions静态类扩展了IObservable<T>的注册方式:

 1  public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext)

 2         {

 3             if (source == null)

 4             {

 5                 throw new ArgumentNullException("source");

 6             }

 7             if (onNext == null)

 8             {

 9                 throw new ArgumentNullException("onNext");

10             }

11             return source.Subscribe(new AnonymousObserver<T>(onNext, Stubs.Throw, Stubs.Nop));

12         }

具体实现我们不具体去关注,但是我们知道在11行,是New了一个匿名的观察者Observer了。

接下来看看FromAsyncPattern

  public static Func<IObservable<TResult>> FromAsyncPattern<TResult>(Func<AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, TResult> end)

这是个静态方法,返回一个返回值类型为IObservable<TResult>,无实参,的委托

先回顾用Rx实现的一个Get方法:

 

 1   public LoginTest()

 2         {

 3        

 4          var func=  Observable.FromAsyncPattern<HttpWebRequest,HttpWebResponse>(Webrequest,WebResponse);

 5          HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://www.baidu.com");

 6            

 7         var observable= func(request);

 8         observable.Subscribe(

 9             (result) =>

10             {

11                 var stream = result.GetResponseStream();

12                 var sr = new StreamReader(stream);

13                 var baiduhttphtml = sr.ReadToEnd();

14             });

15 

16         }

17 

18         IAsyncResult Webrequest(HttpWebRequest request,AsyncCallback callbcak,object ob)

19         {

21             return request.BeginGetResponse(callbcak, request);

22         }

23         HttpWebResponse WebResponse(IAsyncResult result)

24         {

25             var request = result.AsyncState as HttpWebRequest;

26           return (HttpWebResponse)request.EndGetResponse(result);

27         }

这样的Get方式看起来很简洁

昨晚敲了一下,Post方式如下:(回去后在VS2013上用RX,发现他提示我最好用await,Task等新特性来做异步,今晚回去试试,实验室是VS2010)

 1  class MyHttpRequest

 2         {

 3             string PostData;

 4             AsyncCallback save;//用于中间传递

 5             public  IObservable<string> PostMethod(string URL, string PostData)

 6             {

 7                 this.PostData = PostData;

 8                 var func = Observable.FromAsyncPattern<HttpWebRequest,string>(Webrequest, ResponseCallback);//直接返回string

 9                 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL);

10                 request.Method = "POST";

11                 request.ContentType = "application/x-www-form-urlencoded";

12               return  func(request);

13 

14             }

15             IAsyncResult Webrequest(HttpWebRequest request, AsyncCallback callbcak, object ob)

16             {

17                 save = callbcak;//保存CallBack

18                 return request.BeginGetRequestStream(act, request);

19             }

20             void act(IAsyncResult asyncResult)

21             {

22                 HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;

23                 UTF8Encoding encoding = new UTF8Encoding();

24                 Stream _body = request.EndGetRequestStream(asyncResult);

25                 byte[] formBytes = encoding.GetBytes(this.PostData);//这是通过post方式传的

26                 _body.Write(formBytes, 0, formBytes.Length);

27                 _body.Close();

28                 request.BeginGetResponse(save, request);//用保存的CallBack

29 

30             }

31             string ResponseCallback(IAsyncResult asyncResult)

32             {

33                 HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;

34                 WebResponse httpwebresponse = request.EndGetResponse(asyncResult);

35                 Stream stream = httpwebresponse.GetResponseStream();

36                 StreamReader reader = new StreamReader(stream);

37                 return reader.ReadToEnd();

38             }

39         }

好了,现在很清楚了,来试试效果

 1     public LoginTest()

 2         {

 3             //发出一个消息 跟MVVMLight Messenger有点像

 4         var observable=    new MyHttpRequest().PostMethod("http://www.douban.com/j/app/login", "app_name=radio_desktop_win&version=100&[email protected]&password=");

 5         

 6 

 7             //直接在这里订阅一个匿名接收者

 8         observable.Subscribe((result) =>

 9             {

10                 Debug.WriteLine(result);

11             });

12         Debug.WriteLine("我比你先返回,哈哈");

13         }

使用RX方式模拟DoubanFm的登陆

~OK。

可以使用这个方式做我的FM登陆了。

 

你可能感兴趣的:(模拟)