Silverlight_Rest_WCF系列之四:Rest调用者,RestInvoker.

还记得上篇文章中的PUT调用Rest服务的代码吗?不记得没关系,下面就是它的代码。

View Code
#region  使用WebRequest

            WebRequest webRequest 
= WebRequestCreator.ClientHttp.Create(
                
new  Uri( " http://localhost:19598/ProductService.svc/Product " ));
            webRequest.ContentType 
=   " application/json " ;
            webRequest.Method 
=   " PUT " ;
            webRequest.BeginGetRequestStream(requestAsyncCallback 
=>
                {
                    Stream requestStream 
=  webRequest.EndGetRequestStream(requestAsyncCallback);

                    JsonObject jo 
=   new  JsonObject();
                    jo[
" Id " =  Guid.NewGuid().ToString();
                    jo[
" Name " =   " test " ;

                    
string  jsonString  =  jo.ToString();
                    
byte [] buffer  =  System.Text.Encoding.Unicode.GetBytes(jsonString);
                    requestStream.Write(buffer, 
0 , buffer.Length);
                    requestStream.Close();

                    webRequest.BeginGetResponse(responseAsyncCallback 
=>
                        {
                            WebResponse webResponse 
=  webRequest.EndGetResponse(responseAsyncCallback);
                            
using  (StreamReader reader  =   new  StreamReader(webResponse.GetResponseStream()))
                            {
                                
string  result  =  reader.ReadToEnd();
                                
// MessageBox.Show(result);
                                 this .Dispatcher.BeginInvoke(()  =>
                                {
                                    MessageBox.Show(result);
                                });
                            }
                        }, 
null );
                }, 
null );

            
#endregion

如果说每次调用服务都需要写这么多代码的话,那估计程序员会疯的。所以我决定对他进行包装。

在这段代码中有几个地方可以封装。

1:创建WebRequest的代码可以封装。

WebRequest webRequest  = WebRequestCreator.ClientHttp.Create(
                
new  Uri( " http://localhost:19598/ProductService.svc/Product " ));
            webRequest.ContentType 
=   " application/json " ;
            webRequest.Method 
=   " PUT " ;

 

 2:序列化数据到requestStream对象中可以封装。

 Stream requestStream  =  webRequest.EndGetRequestStream(requestAsyncCallback);

                    JsonObject jo 
=   new  JsonObject();
                    jo[
" Id " =  Guid.NewGuid().ToString();
                    jo[
" Name " =   " test " ;

                    
string  jsonString  =  jo.ToString();
                    
byte [] buffer  =  System.Text.Encoding.Unicode.GetBytes(jsonString);
                    requestStream.Write(buffer, 
0 , buffer.Length);
                    requestStream.Close();

3:对返回结果执行的操作可以封装。

WebResponse webResponse  =  webRequest.EndGetResponse(responseAsyncCallback);
                            
using  (StreamReader reader  =   new  StreamReader(webResponse.GetResponseStream()))
                            {
                                
string  result  =  reader.ReadToEnd();
                                
// MessageBox.Show(result);
                                 this .Dispatcher.BeginInvoke(()  =>
                                {
                                    MessageBox.Show(result);
                                });
                            }

 

按照1,2,3的方式我们先从1开始。代码如下:

1:使用GetWebRequest函数获取WebRequest对象,当然了你也可以用factory,但是在目前而言,一个函数就足够了。

///   <summary>
        
///  获取WebRequest对象
        
///   </summary>
        
///   <param name="requestUriString"> 请求的地址 </param>
        
///   <param name="httpMethod"> 请求的方法:GET,PUT,POST,DELETE </param>
        
///   <param name="contentType"> 请求的类型,json:"application/json" </param>
        
///   <returns></returns>
         public   static  HttpWebRequest GetWebRequest( string  requestUriString,
                                                    
string  httpMethod,
                                                    
string  contentType)
        {
            HttpWebRequest request 
=  (HttpWebRequest)WebRequestCreator.ClientHttp.Create( new  Uri(requestUriString));
            request.Method 
=  httpMethod;
            
            
if  ( ! string .IsNullOrWhiteSpace(contentType))
            {
                request.ContentType 
=  contentType;
            }

            
return  request;
        }

2:封装序列化到RequestStream的过程。

Stream requestStream  =  webRequest.EndGetRequestStream(requestAsyncResult);
                SerializeDataToRequestStream(data,requestStream);
                requestStream.Close();

 SerializeDataToRequestStream方法可以对JsonObject,匿名类,DataContract修饰的类进行序列化。

View Code
private   static   void  SerializeDataToRequestStream < T > (T data, Stream requestStream)
        {
            
if  (data.GetType()  ==   typeof (System.Json.JsonObject))
            {
                
string  jsonString  =  data.ToString();
                
byte [] buffer  =  System.Text.Encoding.Unicode.GetBytes(jsonString);
                requestStream.Write(buffer, 
0 , buffer.Length);
            }
            
else   if (data.GetType().FullName.Contains( " AnonymousType " ))  // 如果是匿名类
            {
                
#region  使用反射获取属性和值,可以使用FastInvoker来优化。

                PropertyInfo[] pis 
=  data.GetType().GetProperties();
                System.Json.JsonObject jo 
=   new  System.Json.JsonObject();
                
foreach (PropertyInfo pi  in  pis)
                {
                    jo[pi.Name] 
=  pi.GetValue(data,  null ).ToString();
                }

                
#endregion

                
string  jsonString  =  jo.ToString();
                
byte [] buffer  =  System.Text.Encoding.Unicode.GetBytes(jsonString);
                requestStream.Write(buffer, 
0 , buffer.Length);
            }
            
else
            {
                DataContractJsonSerializer serializer 
=   new  DataContractJsonSerializer( typeof (T));
                serializer.WriteObject(requestStream, data);
            }
        }

 

 3:处理WebResponse。如果T是String类型则直接返回Json的string,否则使用DataContractJsonSerializer 反序列化成对象进行操作。

  ///   <summary>
        
///  处理WebResponse
        
///   </summary>
        
///   <typeparam name="T"> WebResponse返回结果的类型 </typeparam>
        
///   <param name="webResponse"> webResponse对象 </param>
        
///   <param name="action"> 对结果的操作 </param>
         private   static   void  HandleWebResponse < T > (WebResponse webResponse, Action < T >  action)
        {
            
using  (Stream responseStream  =  webResponse.GetResponseStream())
            {
                DataContractJsonSerializer serializer 
=   new  DataContractJsonSerializer( typeof (T));
                
if  ( typeof (T)  ==   typeof ( string ))
                {
                    T responseObject 
=  (T)( object )GetStringFromStream(responseStream);
                    action(responseObject);
                }
                
else
                {
                    T responseObject 
=  (T)serializer.ReadObject(responseStream);
                    action(responseObject);
                }

            }
        }

好了,基本框架已经搭建好了,尝试下调用GET服务吧。

///   <summary>
        
///  调用GET方法
        
///   </summary>
        
///   <typeparam name="T"> 结果的类型 </typeparam>
        
///   <param name="requestUriString"> 请求的地址 </param>
        
///   <param name="action"> 对结果的操作 </param>
         public   static   void  InvokeGet < T > ( string  requestUriString, Action < T >  action)
        {
            HttpWebRequest webRequest 
=  GetWebRequest(requestUriString,  " GET " string .Empty);
            webRequest.BeginGetResponse((asyncResult) 
=>
            {
                WebResponse response 
=  webRequest.EndGetResponse(asyncResult);
                HandleWebResponse(response, action);                
            }, 
null );
        }

调用GET服务比较简单,使用GET从指定的URL下载数据就可以了,那么调用POST,PUT,DELETE呢?

其实原理都比较简单,就是GetRequestStream--->写数据到RequestStream--->GetResponse。

所以可以写一个通用方法来调用PUT,POST,DELETE。

View Code
///   <summary>
        
///  调用PUT/POST/DELETE方法
        
///   </summary>
        
///   <typeparam name="TData"> 请求数据的类型 </typeparam>
        
///   <typeparam name="TResult"> 结果的类型 </typeparam>
        
///   <param name="requestUriString"> 请求的地址 </param>
        
///   <param name="data"> 请求的数据 </param>
        
///   <param name="action"> 对结果的操作 </param>
        
///   <param name="httpMethod"> 请求的具体方法,PUT/POST/DELETE </param>
         public   static   void  InvokePutPostDelete < TData, TResult > ( string  requestUriString, TData data, Action < TResult >  action,  string  httpMethod)
        {
            HttpWebRequest webRequest 
=  GetWebRequest(requestUriString, httpMethod,  " application/json " );

            webRequest.BeginGetRequestStream((requestAsyncResult) 
=>
            {
                Stream requestStream 
=  webRequest.EndGetRequestStream(requestAsyncResult);
                SerializeDataToRequestStream(data,requestStream);
                requestStream.Close();

                webRequest.BeginGetResponse((responseAsyncResult) 
=>
                {
                    WebResponse response 
=  webRequest.EndGetResponse(responseAsyncResult);
                    HandleWebResponse(response, action);
                }, 
null );
            }, 
null );
        }

 

RestInvoker的完整代码如下:

 

View Code
public   class  RestInvoker
    {
        
///   <summary>
        
///  获取WebRequest对象
        
///   </summary>
        
///   <param name="requestUriString"> 请求的地址 </param>
        
///   <param name="httpMethod"> 请求的方法:GET,PUT,POST,DELETE </param>
        
///   <param name="contentType"> 请求的类型,json:"application/json" </param>
        
///   <returns></returns>
         public   static  HttpWebRequest GetWebRequest( string  requestUriString,
                                                    
string  httpMethod,
                                                    
string  contentType)
        {
            HttpWebRequest request 
=  (HttpWebRequest)WebRequestCreator.ClientHttp.Create( new  Uri(requestUriString));
            request.Method 
=  httpMethod;
            
            
if  ( ! string .IsNullOrWhiteSpace(contentType))
            {
                request.ContentType 
=  contentType;
            }

            
return  request;
        }

        
///   <summary>
        
///  调用GET方法
        
///   </summary>
        
///   <typeparam name="T"> 结果的类型 </typeparam>
        
///   <param name="requestUriString"> 请求的地址 </param>
        
///   <param name="action"> 对结果的操作 </param>
         public   static   void  InvokeGet < T > ( string  requestUriString, Action < T >  action)
        {
            HttpWebRequest webRequest 
=  GetWebRequest(requestUriString,  " GET " string .Empty);
            webRequest.BeginGetResponse((asyncResult) 
=>
            {
                WebResponse response 
=  webRequest.EndGetResponse(asyncResult);
                HandleWebResponse(response, action);                
            }, 
null );
        }

        
///   <summary>
        
///  调用PUT方法
        
///   </summary>
        
///   <typeparam name="TData"> 请求数据的类型 </typeparam>
        
///   <typeparam name="TResult"> 结果的类型 </typeparam>
        
///   <param name="requestUriString"> 请求的地址 </param>
        
///   <param name="data"> 请求的数据 </param>
        
///   <param name="action"> 对结果的操作 </param>
         public   static   void  InvokePut < TData,TResult > ( string  requestUriString, TData data, Action < TResult >  action)
        {
            InvokePutPostDelete(requestUriString, data, action, 
" PUT " );
        }

        
///   <summary>
        
///  调用POST方法
        
///   </summary>
        
///   <typeparam name="TData"> 请求数据的类型 </typeparam>
        
///   <typeparam name="TResult"> 结果的类型 </typeparam>
        
///   <param name="requestUriString"> 请求的地址 </param>
        
///   <param name="data"> 请求的数据 </param>
        
///   <param name="action"> 对结果的操作 </param>
         public   static   void  InvokePost < TData, TResult > ( string  requestUriString, TData data, Action < TResult >  action)
        {
            InvokePutPostDelete(requestUriString, data, action, 
" POST " );
        }

        
///   <summary>
        
///  调用DELETE方法
        
///   </summary>
        
///   <typeparam name="TData"> 请求数据的类型 </typeparam>
        
///   <typeparam name="TResult"> 结果的类型 </typeparam>
        
///   <param name="requestUriString"> 请求的地址 </param>
        
///   <param name="data"> 请求的数据 </param>
        
///   <param name="action"> 对结果的操作 </param>
         public   static   void  InvokeDelete < TData, TResult > ( string  requestUriString, TData data, Action < TResult >  action)
        {
            InvokePutPostDelete(requestUriString, data, action, 
" DELETE " );
        }

        
///   <summary>
        
///  调用PUT/POST/DELETE方法
        
///   </summary>
        
///   <typeparam name="TData"> 请求数据的类型 </typeparam>
        
///   <typeparam name="TResult"> 结果的类型 </typeparam>
        
///   <param name="requestUriString"> 请求的地址 </param>
        
///   <param name="data"> 请求的数据 </param>
        
///   <param name="action"> 对结果的操作 </param>
        
///   <param name="httpMethod"> 请求的具体方法,PUT/POST/DELETE </param>
         public   static   void  InvokePutPostDelete < TData, TResult > ( string  requestUriString, TData data, Action < TResult >  action,  string  httpMethod)
        {
            HttpWebRequest webRequest 
=  GetWebRequest(requestUriString, httpMethod,  " application/json " );

            webRequest.BeginGetRequestStream((requestAsyncResult) 
=>
            {
                Stream requestStream 
=  webRequest.EndGetRequestStream(requestAsyncResult);
                SerializeDataToRequestStream(data,requestStream);
                requestStream.Close();

                webRequest.BeginGetResponse((responseAsyncResult) 
=>
                {
                    WebResponse response 
=  webRequest.EndGetResponse(responseAsyncResult);
                    HandleWebResponse(response, action);
                }, 
null );
            }, 
null );
        }

        
///   <summary>
        
///  序列化对象到RequestStream中
        
///   </summary>
        
///   <typeparam name="T"> 请求数据的类型 </typeparam>
        
///   <param name="data"> 请求的数据 </param>
        
///   <param name="requestStream"> RequestStream </param>
         private   static   void  SerializeDataToRequestStream < T > (T data, Stream requestStream)
        {
            
if  (data.GetType()  ==   typeof (System.Json.JsonObject))
            {
                
string  jsonString  =  data.ToString();
                
byte [] buffer  =  System.Text.Encoding.Unicode.GetBytes(jsonString);
                requestStream.Write(buffer, 
0 , buffer.Length);
            }
            
else   if (data.GetType().FullName.Contains( " AnonymousType " ))  // 如果是匿名类
            {
                
#region  使用反射获取属性和值,可以使用FastInvoker来优化。

                PropertyInfo[] pis 
=  data.GetType().GetProperties();
                System.Json.JsonObject jo 
=   new  System.Json.JsonObject();
                
foreach (PropertyInfo pi  in  pis)
                {
                    jo[pi.Name] 
=  pi.GetValue(data,  null ).ToString();
                }

                
#endregion

                
string  jsonString  =  jo.ToString();
                
byte [] buffer  =  System.Text.Encoding.Unicode.GetBytes(jsonString);
                requestStream.Write(buffer, 
0 , buffer.Length);
            }
            
else
            {
                DataContractJsonSerializer serializer 
=   new  DataContractJsonSerializer( typeof (T));
                serializer.WriteObject(requestStream, data);
            }
        }

        
///   <summary>
        
///  处理WebResponse
        
///   </summary>
        
///   <typeparam name="T"> WebResponse返回结果的类型 </typeparam>
        
///   <param name="webResponse"> webResponse对象 </param>
        
///   <param name="action"> 对结果的操作 </param>
         private   static   void  HandleWebResponse < T > (WebResponse webResponse, Action < T >  action)
        {
            
using  (Stream responseStream  =  webResponse.GetResponseStream())
            {
                DataContractJsonSerializer serializer 
=   new  DataContractJsonSerializer( typeof (T));
                
if  ( typeof (T)  ==   typeof ( string ))
                {
                    T responseObject 
=  (T)( object )GetStringFromStream(responseStream);
                    action(responseObject);
                }
                
else
                {
                    T responseObject 
=  (T)serializer.ReadObject(responseStream);
                    action(responseObject);
                }

            }
        }

        
///   <summary>
        
///  从Stream中获取String
        
///   </summary>
        
///   <param name="stream"></param>
        
///   <returns></returns>
         public   static   string  GetStringFromStream(Stream stream)
        {
            
byte [] buffer  =   new   byte [ 32768 ];
            stream.Position 
=   0 // 重置读取位置
             while  ( true )
            {
                
int  read  =  stream.Read(buffer,  0 , buffer.Length);
                
if  (read  <=   0 )
                    
break ;
            }

            
return  System.Text.Encoding.UTF8.GetString(buffer,  0 , ( int )stream.Length);
        }

        
///   <summary>
        
///  复制流
        
///   </summary>
        
///   <param name="input"> 输入流 </param>
        
///   <param name="output"> 输出流 </param>
         private   static   void  CopyStream(Stream input, Stream output)
        {
            
byte [] buffer  =   new   byte [ 32768 ];
            input.Position 
=   0 // 重置读取位置
             while  ( true )
            {
                
int  read  =  input.Read(buffer,  0 , buffer.Length);
                
if  (read  <=   0 )
                    
return ;
                output.Write(buffer, 
0 , read);
            }
        }

    }

 

但是我们还没有解决跨线程问题,还记得上篇文章中的this.Dispatcher.BeginInvoker吗?

但是在某些特定情况下,客户端不想调用BeginInvoker。

我们下回要修改RestInvoker,让它可以跨线程。 下回分解。。。

你可能感兴趣的:(silverlight)