• 用泛型减少重复代码,使代码更合理、更优雅


    有这样一个场景,需要对接接口,以获取取得数据。

    例如获取订单列表

    接口请求参数(json格式):

     1 {
     2   //公共头部
     3   "head":{
     4     "method":"getOrders",       //接口方法
     5     "sign":"xxxx"               //签名
     6   },
     7   //私有主体
     8   "body":{
     9     "userId":"1",               //用户ID
    10     "numPerPage":10,           //页大小
    11     "pageIdx":1             //页码
    12   }
    13 }
    View Code

    接口响应结果(json格式):

     1 {
     2   "head":{
     3     "code":1,      //状态码
     4     "errMsg":"成功"  //消息
     5   },
     6   "body":{
     7     "pageCount":value,
     8     "pageIdx":value,
     9     "orders":[
    10       {
    11         "orderNo":value,
    12         "orderPrice":value,
    13         "orderTime":value,
    14       }
    15     ]
    16     "status":value,
    17     "orderStatus":value
    18     省略...
    19   }
    20 }
    View Code

      通过观察请求参数和响应结果,会发现有部分字段是公共的,并且与接口交互的方法,大部分都是相同的,这里也可以提取封装,将不稳定容易出错的代码集中到一个地方;而如果对每个接口方法都进行一遍对接,重复的代码会不少,也很容易出错(对copy代码,吃过相当多的亏),所以对重复代码进行适当的封装,减少不必要的冗余,让代码结构更简单明了。

    首先是提取公共的请求实体容器BaseWhere<T>:

     1 /// <summary>
     2 /// 公共头部
     3 /// <para>
     4 /// 用于与接口通讯,发送请求数据的容器
     5 /// 数据访问层使用
     6 /// </para>
     7 /// </summary>
     8 /// <typeparam name="T"></typeparam>
     9 public class BaseWhere<T> where T : new()
    10 {
    11     private headBaseWhere _head = new headBaseWhere();
    12 
    13     /// <summary>
    14     /// 公共头部
    15     /// </summary>
    16     public headBaseWhere head { get; set; }
    17 
    18     private T _body = new T();
    19 
    20     /// <summary>
    21     /// 私有主体
    22     /// </summary>
    23     public T body { get; set; }
    24 }
    25 
    26 public class headBaseWhere
    27 {
    28     /// <summary>
    29     /// 接口方法
    30     /// </summary>
    31     public String method { get; set; }
    32 
    33     /// <summary>
    34     /// 签名
    35     /// </summary>
    36     public String sign { get; set; }
    37 }
    View Code

    接下来是提取公共的响应实体容器BaseResult<T>:

     1 /// <summary>
     2 /// 返回报文报文头参数
     3 /// <para>
     4 /// 用于与接口通讯,接收返回数据的容器
     5 /// 数据访问层使用
     6 /// </para>
     7 /// </summary>
     8 /// <typeparam name="T"></typeparam>
     9 public class BaseResult<T> where T : new()
    10 {
    11     private headBaseResult _head = new headBaseResult();
    12     /// <summary>
    13     /// 公共头部
    14     /// </summary>
    15     public headBaseResult head { get; set; }
    16 
    17     private T _body = new T();
    18     /// <summary>
    19     /// 私有主体
    20     /// </summary>
    21     public T body { get; set; }
    22 }
    23 
    24 public class headBaseResult
    25 {
    26         /// <summary>
    27     /// 状态码
    28     /// </summary>
    29     public String code { get; set; }
    30 
    31         /// <summary>
    32     /// 消息
    33     /// </summary>
    34     public String msg { get; set; }
    35 }
    View Code

    然后定义订单列表的请求实体OrdersPara和响应实体OrdersResult:

     1 /// <summary>
     2 /// 订单列表(请求实体)
     3 /// </summary>
     4 public class OrdersPara
     5 {
     6     public string userId { get; set; }
     7 
     8     public int numPerPage { get; set; }
     9 
    10     public int pageIdx { get; set; }
    11 }
    12 
    13 /// <summary>
    14 /// 订单列表(响应实体)
    15 /// </summary>
    16 public class OrdersResult
    17 {
    18     private IList<Order> _orders = new List<Order>();
    19 
    20     public int pageCount { get; set; }
    21     public int pageIdx { get; set; }
    22     public IList<Order> orders { get { return _orders; } set { _orders = value; } }
    23 }
    24 
    25 public class Order 
    26 {
    27     private IList<OrderDetail> _detail = new List<OrderDetail>();
    28 
    29     public string orderNo { get; set; }
    30     public decimal orderPrice { get; set; }
    31     public string orderTime { get; set; }
    32     public int status { get; set; }
    33     public int orderStatus { get; set; }
    34     public int activityID { get; set; }
    35     public string mobileNo { get; set; }
    36 }
    View Code

    公共的请求方法WebAPIHelper<T>.POST(obj):

     1 public static class WebAPIHelper<T> where T : new()
     2 {
     3     public static BaseResult<T> Post(Object postData)
     4     {
     5         StringBuilder strResult = new StringBuilder();
     6 
     7         //创建HttpWebRequest请求
     8         HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(Settings.APIURL);
     9         request.Method = "POST";
    10         request.ContentType = "application/x-www-form-urlencoded";
    11         //根据接口的要求序列化请求参数
    12         String strParams = JsonConvert.SerializeObject(postData);
    13         UTF8Encoding encoding = new UTF8Encoding();
    14         request.ContentLength = encoding.GetByteCount(strParams);
    15         request.Credentials = CredentialCache.DefaultCredentials;
    16 
    17         try
    18         {
    19             //创建字节流
    20             using (Stream reqStream = request.GetRequestStream())
    21             {
    22                 reqStream.Write(encoding.GetBytes(strParams), 0, encoding.GetByteCount(strParams));
    23             }
    24             //获取回传信息
    25             using (WebResponse response = request.GetResponse())
    26             {
    27                 Stream streamResult = response.GetResponseStream();
    28                 using (StreamReader reader = new StreamReader(streamResult))
    29                 {
    30                     strResult.Append(reader.ReadToEnd());
    31                 }
    32             }
    33         }
    34         catch (Exception ex)
    35         {
    36         }
    37 
    38         BaseResult<T> result = new BaseResult<T>();
    39         try
    40         {
    41             result = JsonConvert.DeserializeObject<BaseResult<T>>(strResult.ToString());
    42         }
    43         catch (Exception ex)
    44         {
    45         }
    46 
    47         if (result == null)
    48         {
    49             result = new BaseResult<T>();
    50         }
    51 
    52         if(result.body == null)
    53         {
    54             result.body = new T();
    55         }
    56 
    57         return result;
    58     }
    59 }
    View Code

    调用示例:

    public QueryOrdersResult Get(QueryOrdersPara para)
    {
        BaseWhere<OrdersPara> where = new BaseWhere<OrdersPara>();
        where.head.method = "qryOrders";
        where.body.userId = para.userId;
        where.body.pageIdx = para.pageIdx;
        where.body.numPerPage = para.numPerPage;
        
        BaseResult<OrdersResult> result = WebAPIHelper<OrdersResult>.Post(where);
        return result.body;
    }

    这样完成了重复部分代码的封装提取,还可以更进一步在WebAPIHelper<T>.POST(obj)方法里面,添加统一异常处理,如接口服务器异常、超时之类的。

    如有不当之处,请大家多多指教。

  • 相关阅读:
    费马小定理
    Codeforces Round #448
    [Offer收割]编程练习赛37
    Educational Codeforces Round 33
    Codeforces Round #447
    Codeforces Round #446
    A Great Alchemist 最详细的解题报告
    A Mountaineer 最详细的解题报告
    hihoCoder 1040 矩阵判断 最详细的解题报告
    hihoCoder 1039 字符消除 最详细的解题报告
  • 原文地址:https://www.cnblogs.com/chen-yu/p/4680651.html
Copyright © 2020-2023  润新知