zoukankan      html  css  js  c++  java
  • 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,让它可以跨线程。 下回分解。。。

  • 相关阅读:
    Spring框架总结(二)
    java.lang.ClassCastException: com.liuyang.annocation.UserAction cannot be cast to com.liuyang.annocation2.UserAction at com.liuyang.annocation2.App.test
    Spring框架总结(一)
    Error creating bean with name 'us' defined in class path resource [com/liuyang/test/DI/beans2.xml]: Cannot resolve reference to bean 'daoa' while setting bean property 'daoa'; nested exception is org.
    互联网系统架构的演进
    重新理解:ASP.NET 异步编程(转)
    Git初级使用教程(转)
    JavaScript开发规范要求
    大型网站架构演化发展历程(转)
    Bootstrap 学习(1)
  • 原文地址:https://www.cnblogs.com/LoveJenny/p/2041549.html
Copyright © 2011-2022 走看看