<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      【C#|.NET】從細(xì)節(jié)出發(fā)(一) 通用接口 aop dto 相關(guān)

      2013-03-25 16:14  熬夜的蟲子  閱讀(4549)  評論(2)    收藏  舉報

      系列文章完成后 源碼發(fā)布在我的GIT上 https://github.com/dubing/

      文章僅代表個人觀點(diǎn)  旨在交流 歡迎討論


      背景

        隨著信息化的普及,信息系統(tǒng)越來越多,通常不同系統(tǒng)是采用不同的技術(shù)基于不同平臺開發(fā)的,缺乏統(tǒng)一規(guī)劃、統(tǒng)一數(shù)據(jù)標(biāo)準(zhǔn)、統(tǒng)一調(diào)用接口,因此系統(tǒng)之間的交互變得很困難.通常大家在需要一個現(xiàn)有系統(tǒng)提供某方面功能的話就會讓開發(fā)人員提供個接口,webservice接口也好,標(biāo)準(zhǔn)http接口也好。然后需求不停的變更,代碼不停的迭代。隨著應(yīng)用端量的增多,對于類似業(yè)務(wù)邏輯提供的數(shù)據(jù)格式,內(nèi)容的特殊處理,dto的設(shè)計等等都在變化。用.Net的同學(xué)會了解多一些,用webservice的話,應(yīng)用端會生成代理類。服務(wù)端每次更新對應(yīng)應(yīng)用端都要同步更新。至此,我們引出第一個細(xì)節(jié)問題,解決服務(wù)端與應(yīng)用端的強(qiáng)依賴,設(shè)計通用的接口規(guī)范。


      技術(shù)點(diǎn)

        1. AOP(切面)

        2. JavaScriptSerializer (json序列化)

        3. DTO設(shè)計


      實(shí)現(xiàn)

        先設(shè)計一個通用的接口類  

          /// <summary>
          /// 對象處理返回的結(jié)果接口
          /// </summary>
          /// <remarks>
          /// 建議在代碼調(diào)用返回值中都采用此類實(shí)例為返回值<br />
          /// 一般ResultNo小于0表示異常,0表示成功,大于0表示其它一般提示信息
          /// </remarks>
          public interface IAOPResult 
          {
              /// <summary>
              /// 返回代碼
              /// </summary>
              int ResultNo { get; }
      
              /// <summary>
              /// 對應(yīng)的描述信息
              /// </summary>
              string ResultDescription { get; }
      
              /// <summary>
              /// 相應(yīng)的附加信息
              /// </summary>
              object ResultAttachObject { get; }
      
              /// <summary>
              /// 內(nèi)部AOPResult
              /// </summary>
              IAOPResult InnerAOPResult { get; }
      
              /// <summary>
              /// 處理結(jié)果是否成功(ResultNo == 0)
              /// </summary>
              bool IsSuccess { get; }
      
              /// <summary>
              /// 處理結(jié)果是否失敗(ResultNo != 0 )
              /// </summary>
              bool IsNotSuccess { get; }
      
              /// <summary>
              /// 處理結(jié)果是否失敗(ResultNo < 0 )
              /// </summary>
              bool IsFailed { get; }
      
              /// <summary>
              /// 已處理,但有不致命的錯誤(ResultNo > 0)
              /// </summary>
              bool IsPassedButFailed { get; }
      
              /// <summary>
              /// 如果處理失敗,則拋出異常 
              /// </summary>
              /// <returns>返回本身</returns>
              IAOPResult ThrowErrorOnFailed();
          }
      

        設(shè)計一個里AOPResult實(shí)現(xiàn)這個接口,類中添加Serializable屬性表明可序列化,應(yīng)用到我們的具體的demo如下

              [WebMethod(Description = "檢查購物車中的禮品")]
              [SoapHeader("header")]
              public AOPResult CheckGiftForCart(List<CartLineDTO> carlist, bool returnflag)
              {
                  ValidateAuthentication();
                  return (AOPResult)CartGiftCenter.GiftService.CheckGiftForCart(carlist, returnflag);
              }
      
              [WebMethod(Description = "獲取所有的贈品信息")]
              [SoapHeader("header")]
              public AOPResult GetGiftList()
              {
                  ValidateAuthentication();
                  var result = (AOPResult)CartGiftCenter.GiftService.GetModelList();
                  if(result.IsSuccess)
                  {
                      result.ResultAttachObject = result.ResultAttachObject.ObjectToJson();
                  }
                  return result;
              }
      
              [WebMethod(Description = "根據(jù)Id獲得組信息")]
              [SoapHeader("header")]
              public AOPResult GetGroupInfoByID(int Id)
              {
                   ValidateAuthentication();
                   var result = (AOPResult)CartGiftCenter.GroupService.GetModelInfoById(Id);
                   if (result.IsSuccess)
                   {
                       var resultobj = result.ResultAttachObject as GiftGroup;
                       result.ResultAttachObject = new GroupLineDTO
                                                       {
                                                           GroupId = (int)resultobj.GroupId,                                                
                                                       }.ObjectToJson();
      
                   }
                   return result;
              }       
      

        從上面的例子我們可以看出所有的服務(wù)方法都采用了相同的返回類型。AOPResult中可以存對象,可以存數(shù)組,具體由自己定義。如果返回的是對象我們需要將他序列化成json方式。序列化方法參照下面

          public static class JsonExtensions
          {
              private static JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
      
              [DebuggerStepThrough]
              public static string ObjectToJson(this object obj)
              {
                  return javaScriptSerializer.Serialize(obj);
              }
      
              [DebuggerStepThrough]
              public static T JsonToObject<T>(this string json)
              {
                  if (string.IsNullOrEmpty(json)) return default(T);
                  return javaScriptSerializer.Deserialize<T>(json);
              }
          }
      

        這么做的優(yōu)缺點(diǎn)是什么,優(yōu)點(diǎn)是服務(wù)協(xié)議的雙方有了共同的標(biāo)準(zhǔn),應(yīng)用端不再完全依賴于代理,也就是說服務(wù)端的變更不會直接影響到應(yīng)用端。舉個最簡單的例子,應(yīng)用a先向服務(wù)端索取一個對象A,A中包含c屬性,后來b也想服務(wù)端索取對象A,但是需要包含d屬性。服務(wù)器端更新重新build。按照普通設(shè)計a變也需要重新build引用新的服務(wù)代理。那么按照這個設(shè)計a便只需要從A中提取c就可以,不管服務(wù)端以后如何變更只要c屬性還在,結(jié)構(gòu)為改變就不需要重新build。

        應(yīng)用端簡單示例

                  var b = CartGiftCenter.GiftService.GetModelList();
                  string message =b.ResultDescription;
                  var gift = b.ResultAttachObject as List<GiftDetail>;
      

        另一外的主要的有點(diǎn)就是可以統(tǒng)一的切面編程,aop的概念這里就不多說了。利用aop的特點(diǎn)我們可以對服務(wù)的反饋?zhàn)鹘y(tǒng)一的操作、檢查。例如系統(tǒng)認(rèn)證、內(nèi)容過濾等等。這里推薦一篇簡單務(wù)實(shí)的文章 http://blog.csdn.net/yanghua_kobe/article/details/6917228

        上文中所附的簡單切面輔助類

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Web;
      using System.Diagnostics;
      
      /// <summary>
      ///AspectF 的摘要說明
      /// </summary>
      public class AspectF
      {
          internal Action<Action> Chain = null;
      
          internal Delegate WorkDelegate;
      
          [DebuggerStepThrough]
          public void Do(Action work)
          {
              if (this.Chain==null)
              {
                  work();
              }
              else
              {
                  this.Chain(work);
              }
          }
      
          [DebuggerStepThrough]
          public TReturnType Return<TReturnType>(Func<TReturnType> work)
          {
              this.WorkDelegate = work;
      
              if (this.Chain==null)
              {
                  return work();
              }
              else
              {
                  TReturnType returnValue = default(TReturnType);
                  this.Chain(() =>
                  {
                      Func<TReturnType> workDelegate = WorkDelegate as Func<TReturnType>;
                      returnValue = workDelegate();
                  });
                  return returnValue;
              }
          }
      
          public static AspectF Define
          {
              [DebuggerStepThrough]
              get
              {
                  return new AspectF();
              }
          }
      
          [DebuggerStepThrough]
          public AspectF Combine(Action<Action> newAspectDelegate)
          {
              if (this.Chain==null)
              {
                  this.Chain = newAspectDelegate;
              }
              else
              {
                  Action<Action> existingChain = this.Chain;
                  Action<Action> callAnother = (work) =>
                      existingChain(() => newAspectDelegate(work));
                  this.Chain = callAnother;
              }
      
              return this;
          }
      
          public static void Retry(int retryDuration, int retryCount, Action<Exception> errorHandler, Action retryFaild, Action work)
          {
              do
              {
                  try
                  {
                      work();
                  }
                  catch (Exception ex)
                  {
                      errorHandler(ex);
                      System.Threading.Thread.Sleep(retryDuration);
                      throw;
                  }
              } while (retryCount-- > 0);
      
          }
      }
      
      public static class AspectExtensions
      {
          [DebuggerStepThrough]
          public static void DoNothing()
          {
      
          }
      
          [DebuggerStepThrough]
          public static void DoNothing(params object[] whatever)
          {
      
          }
      
          [DebuggerStepThrough]
          public static AspectF Delay(this AspectF aspect, int milliseconds)
          {
              return aspect.Combine((work) =>
              {
                  System.Threading.Thread.Sleep(milliseconds);
                  work();
              });
          }
      
          [DebuggerStepThrough]
          public static AspectF MustBeNonNull(this AspectF aspect,params object[] args)
          {
              return aspect.Combine((work) =>
              {
                  for (int i = 0; i < args.Length; i++)
                  {
                      object arg = args[i];
                      if (arg==null)
                      {
                          throw new ArgumentException(string.Format("Parameter at index {0} is null", i));
                      }
                  }
                  work();
              });
          }
      
          public static AspectF MustBeNonDefault<T>(this AspectF aspect, params T[] args) where T : IComparable
          {
              return aspect.Combine((work) =>
              {
                  T defaultvalue = default(T);
                  for (int i = 0; i < args.Length; i++)
                  {
                      T arg = args[i];
                      if (arg==null||arg.Equals(defaultvalue))
                      {
                          throw new ArgumentException(string.Format("Parameter at index {0} is null", i));
                      }
                  }
                  work();
              });
          }
      
          public static AspectF WhenTrue(this AspectF aspect, params Func<bool>[] conditions)
          {
              return aspect.Combine((work) =>
              {
                  foreach (Func<bool> condition in conditions)
                  {
                      if (!condition())
                      {
                          return;
                      }
                  }
                  work();
              });
          }
      
          [DebuggerStepThrough]
          public static AspectF RunAsync(this AspectF aspect, Action completeCallback)
          {
              return aspect.Combine((work) => work.BeginInvoke(asyncresult =>
              {
                  work.EndInvoke(asyncresult); completeCallback();
              }, null));
          }
      
          [DebuggerStepThrough]
          public static AspectF RunAsync(this AspectF aspect)
          {
              return aspect.Combine((work) => work.BeginInvoke(asyncresult =>
              {
                  work.EndInvoke(asyncresult);
              }, null));
          }
      }
      

        缺點(diǎn):性能問題,首先是對象序列和反序列化的開銷,其次是對象強(qiáng)制轉(zhuǎn)換的開銷,最后是傳統(tǒng)aop反射的開銷。不過對于一般項(xiàng)目利遠(yuǎn)遠(yuǎn)大于弊。

        再說DTO,這個概念和我們上述的場景完全是相反的論調(diào)。了解j2ee的同學(xué)對這些術(shù)語都很熟悉,Data Transfer Object數(shù)據(jù)傳輸對象,主要用于遠(yuǎn)程調(diào)用等需要大量傳輸對象的地方。比如我們一張表有20個字段,那么對應(yīng)的持久對象(persistant object,簡稱po)就有20個屬性。但是我們界面上只要顯示10個字段,應(yīng)用端用webservice來獲取數(shù)據(jù),沒有必要把整個PO對象傳遞到應(yīng)用端,這時我們就可以用只有這10個屬性的DTO來傳遞結(jié)果到客戶端。

        前文我們介紹AOPResult的時候,不考慮帶寬也不考慮數(shù)據(jù)的安全策略。實(shí)際場景下,DTO的設(shè)計也需要考慮很多方面。我自己也不敢說自己設(shè)計的就是最合理的,我只分享下我的設(shè)計經(jīng)驗(yàn),在數(shù)據(jù)庫通用(各個系統(tǒng)都能訪問)的前提下,DTO只提供ID等表示字段,或者根據(jù)業(yè)務(wù)場景,如果應(yīng)用端需要的內(nèi)容不多可以設(shè)計成冗余類型甚至設(shè)計成PO。在帶寬充足的場景下例如內(nèi)網(wǎng)項(xiàng)目,放心的填充吧,沒那么多性能元素需要考慮。一般場景下,則需要考慮的多些,看方法的使用頻度,公網(wǎng)項(xiàng)目中dto中少存敏感字段等等。


      題外

        本篇先到此,有疑問或者有其他想法的同學(xué)歡迎提出來一起討論,下個章節(jié)一起再研究下如何利用泛型最簡單的操作多種類型數(shù)據(jù)庫。

        

        

       

      主站蜘蛛池模板: 一卡2卡三卡4卡免费网站| 在线观看亚洲精品国产| 骚虎视频在线观看| 久久69国产精品久久69软件| 九九热免费精品在线视频| 精品熟女亚洲av在线观看| 国产成人无码免费看片软件| 乱码中文字幕| 国产精品区一二三四久久| 久久国产精品老女人| 人人澡超碰碰97碰碰碰| 老熟妇仑乱一区二区视頻| 我要看特黄特黄的亚洲黄片| 亚洲最大成人免费av| 亚洲高潮喷水无码AV电影| 双流县| 亚洲美免无码中文字幕在线| 疯狂做受XXXX高潮国产| 国产麻豆精品一区一区三区| 色老板精品视频在线观看| 一级女性全黄久久片免费| 成人无码午夜在线观看| 天堂V亚洲国产V第一次| 另类 专区 欧美 制服| 成人免费A级毛片无码网站入口 | 蜜桃av无码免费看永久| 国产高清在线精品一区| 色天使亚洲综合一区二区| 少妇和邻居做不戴套视频| 久久久久免费看成人影片| 我要看亚洲黄色太黄一级黄| 中文字幕无码免费久久| 国产精品免费中文字幕| 亚洲熟妇在线视频观看| 欧美日韩精品一区二区在线观看 | 三上悠亚久久精品| 精品尤物TV福利院在线网站| 国产免费无遮挡吃奶视频| 国产午夜精品福利视频| 亚洲av高清一区二区三| 好硬好湿好爽好深视频|