海水正藍

          面朝大海,春暖花開
          posts - 145, comments - 29, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          1. 上下文概述

          上下文:其實就是一個邏輯上的業務、功能區域。在這個邏輯區域里可以有效的進行管理,算是一種制度的約束,也可以理解為某種范圍類的數據共享

          其實在很多應用框架中到處可以看見上下文的概念,包括.NET本身的設計就建立在這種思想上的。實例化的對象默認存在于系統中的默認上下文中,我們可以構建自己的上下文將對象在運行時進行合理的管理。

          在ASP.NET框架中比較經典的就是HttpContext上下文對象。所有的運行時對象都會邏輯歸屬到HttpContext上下文中來,如:我們可以使用Request、Response等對象訪問HTTP處理的生命周期數據。

          在Remoting中跨AppDomin訪問也是建立在上下文基礎上的,請求的消息通過隧道后序列化到達調用發。王清培版權所有,轉載請給出署名

          在這些強大的應用框架背后總有著讓人難以琢磨的設計秘方,諸多的設計原則、設計模式、豐富的實踐經驗都將是框架穩定運行的基石。Context算是一個比較完美的邏輯范圍設計模式。[王清培版權所有,轉載請給出署名]

          那么就讓我們來領略一下上下文的奧秘吧!

          2. 上下文的一般應用

          上下文的設計思想絕對的美妙,很多地方一旦進行上下文抽象就能解決很多問題。比如在Remoting中我們可以動態的在上下文中加入很 多擴展對上下文中的所有對象進行強制管理,比如:調用某一個方法我們需要進行安全檢查,我們可以編寫一個滿足自己當前項目需求的安全認證插件動態的注入到 上下文管理器區域中,在這個地方就體現出上下文的設計優勢。

          在Web編程中,由于它有著與Winfrom編程很大的差異性,需要將同一組對象同時服務于N個客戶端進行使用,而在Winfrom中基本上都是屬于單線程的,當然可以手動的開啟多線程并行操作。對于ASP.NET每當有新的請求處理時,框架會自動開啟新的線程去處理當前的調用,然后這個時候就是需要一個相對于之前操作的獨立上下文數據環境,而不是在同一個服務器上的所有線程都是共享的。王清培版權所有,轉載請給出署名

          那么我們就需要將當前的HTTP處理的相關數據納入到一個邏輯的上下文進行管理和數據共享。

          這么多的優勢存在,看來我們是有必要嘗試一下這中設計模式了。那么就目前系統開發框架而言我們的上下文能用在哪里呢?我想當務之急就是將分層架構中的所有單條線上的對象進行上下文管理。[王清培版權所有,轉載請給出署名]

          典型的三層架構:

          在一般的三層架構開發過程中我們的調用關系基本都是這樣的,利用上下文設計模式我們可以將本來鼓勵的對象進行合理的管理。上圖中User對象線將是屬于User上下文的,Order對象線將是屬于Order上下文的。大家互不干擾,可以在這個邏輯上下文中共享數據、設置調用安全策略、設計日志記錄方式、甚至可以計算每個方法的性能。
          BLL的調用代碼:

           

          1. View Code   
          2.  /*** 
          3.   * author:深度訓練 
          4.   * blog:http://wangqingpei557.blog.51cto.com/ 
          5.   * **/  
          6.  using System;  
          7.  using System.Collections.Generic;  
          8.  using System.Text;  
          9.  using System.Reflection;  
          10.    
          11.  namespace ConsoleApplication1.BLL  
          12.  {  
          13.      [ContextModule.ContextEveningBound(IsEvening = true)]  
          14.      public class BLL_Order : ContextModule.ContextModuleBaseObject<BLL_Order>  
          15.      {  
          16.          DAL.DAL_Order dal_order = new DAL.DAL_Order();  
          17.    
          18.          [ContextModule.ContextExceptionHandler(OperationSort = 1)]  
          19.          public Model.Model_Order InsertOrderSingle(Model.Model_Order ordermodel)  
          20.          {  
          21.              return ContextModule.ContextAction.PostMethod<DAL.DAL_Order, Model.Model_Order>(  
          22.                  dal_order, dal_order.GetMethodInfo("InsertOrderSingle"), ordermodel);  
          23.          }  
          24.          [ContextModule.ContextExceptionHandler(OperationSort = 1)]  
          25.          public void SendOrder(Model.Model_Order ordermodel)  
          26.          {  
          27.              ContextModule.ContextAction.PostMethod<DAL.DAL_Order, object>(  
          28.                 dal_order, dal_order.GetMethodInfo("SendOrder"), ordermodel);  
          29.          }  
          30.      }  
          31.  }  


          DAL的執行代碼:

           

          1. View Code   
          2.  /*** 
          3.   * author:深度訓練 
          4.   * blog:http://wangqingpei557.blog.51cto.com/ 
          5.   * **/  
          6.  using System;  
          7.  using System.Collections.Generic;  
          8.  using System.Text;  
          9.    
          10.  namespace ConsoleApplication1.DAL  
          11.  {  
          12.      [ContextModule.ContextEveningBound(IsEvening = true)]  
          13.      public class DAL_Order : ContextModule.ContextModuleBaseObject<DAL_Order>  
          14.      {  
          15.          [ContextModule.ContextLogHandler(OperationSort = 1)]  
          16.          [ContextModule.ContextSecurityHanlder(OperationSort = 2)]  
          17.          public Model.Model_Order InsertOrderSingle(Model.Model_Order ordermodel)  
          18.          {  
          19.              return new Model.Model_Order() { OrderGuid = Guid.NewGuid(), OrderTime = DateTime.Now };  
          20.          }  
          21.          [ContextModule.ContextLogHandler(OperationSort = 1)]  
          22.          public void SendOrder(Model.Model_Order ordermodel)  
          23.          {  
          24.              Console.WriteLine("訂單發送成功!");  
          25.          }  
          26.      }  
          27.  }  

          上述代碼是我模擬一個上下文的執行過程。

          3. 上下文共享區域

          在每個獨立的上下文環境中應該有一片共享的數據存儲區域,以備多個上下文對象訪問。這種方便性多半存在于項目比較緊張的修改需求的時候或者加新業務的時候擴展方法用的。

          BLL調用代碼:

          1. View Code   
          2.  [ContextModule.ContextExceptionHandler(OperationSort = 1)]  
          3.          public void UpdateOrderSingle()  
          4.          {  
          5.              Model.Model_Order ordermodel = new Model.Model_Order() { OrderGuid = Guid.NewGuid(), OrderTime = DateTime.Now };  
          6.              //放入上下文共享對象池  
          7.              ContextModule.ContextRuntime.CurrentContextRuntime.SetValue("updateorder", ordermodel);  
          8.              ContextModule.ContextAction.PostMethod<DAL.DAL_Order, object>(  
          9.                  dal_order, dal_order.GetMethodInfo("UpdateOrderSingle"), null);  
          10.          }  


          DAL執行代碼:DAL執行代碼:DAL執行代碼:DAL執行代碼:

          1. [ContextModule.ContextLogHandler(OperationSort = 1)]  
          2.         public void UpdateOrderSingle()  
          3.         {  
          4.             Model.Model_Order ordermodel =  
          5.                 ContextModule.ContextRuntime.CurrentContextRuntime.GetValue("updateorder") as Model.Model_Order;  
          6.         }  


          4. 上下文運行時環境

          對于上下文運行時環境的構建需要考慮到運行時是共享的上下文對象。對于納入上下文管理的所有對象都需要共享或者說是受控于上下文運行時。

          上下文構建:


          1. /*** 
          2.  * author:深度訓練 
          3.  * blog:http://wangqingpei557.blog.51cto.com/ 
          4.  * **/  
          5. using System;  
          6. using System.Collections.Generic;  
          7. using System.Text;  
          8.   
          9. namespace ContextModule  
          10. {  
          11.     /// <summary>  
          12.     /// 上下文運行時環境。  
          13.     /// 上下文邏輯運行時環境,環境中的功能都是可以通過附加進來的。  
          14.     /// </summary>  
          15.     public class ContextRuntime : IDisposable  
          16.     {  
          17.         #region IDisposable成員  
          18.         void IDisposable.Dispose()  
          19.         {  
          20.             _currentContextRuntime = null;  
          21.         }  
          22.         #endregion  
          23.   
          24.         protected ContextRuntime() { }  
          25.         private DateTime _initTime = DateTime.Now;  
          26.         /// <summary>  
          27.         /// 獲取運行時創建上下文的時間  
          28.         /// </summary>  
          29.         public virtual DateTime InitTime { get { return _initTime; } }  
          30.         private Dictionary<object, object> _runTimeResource = new Dictionary<object, object>();  
          31.         private ContextFilterHandlerMap _filterMap = new ContextFilterHandlerMap();  
          32.         /// <summary>  
          33.         /// 獲取上下文中的方法、類過濾器映射表  
          34.         /// </summary>  
          35.         public ContextFilterHandlerMap FilterMap { get { return _filterMap; } }  
          36.         private Guid _initPrimaryKey = Guid.NewGuid();  
          37.         /// <summary>  
          38.         /// 獲取運行時創建上下文的唯一標識  
          39.         /// </summary>  
          40.         public virtual Guid InitPrimaryKey { get { return _initPrimaryKey; } }  
          41.         /// <summary>  
          42.         /// 獲取上下文共享區域中的數據  
          43.         /// </summary>  
          44.         /// <param name="key">數據Key</param>  
          45.         /// <returns>object數據對象</returns>  
          46.         public virtual object GetValue(object key)  
          47.         {  
          48.             return _runTimeResource[key];  
          49.         }  
          50.         /// <summary>  
          51.         /// 設置上下文共享區域中的數據  
          52.         /// </summary>  
          53.         /// <param name="key">數據Key</param>  
          54.         /// <param name="value">要設置的數據對象</param>  
          55.         public virtual void SetValue(object key, object value)  
          56.         {  
          57.             _runTimeResource[key] = value;  
          58.         }  
          59.   
          60.         [ThreadStatic]  
          61.         private static ContextRuntime _currentContextRuntime;  
          62.         /// <summary>  
          63.         /// 獲取當前上下文運行時對象.  
          64.         /// </summary>  
          65.         public static ContextRuntime CurrentContextRuntime { get { return _currentContextRuntime; } }  
          66.         /// <summary>  
          67.         /// 開始運行時上下文  
          68.         /// </summary>  
          69.         /// <returns>ContextRuntime</returns>  
          70.         public static ContextRuntime BeginContextRuntime()  
          71.         {  
          72.             //可以通過配置文件配置上下文運行時環境的參數。這里只是實現簡單的模擬。  
          73.             _currentContextRuntime = new ContextRuntime();  
          74.             return _currentContextRuntime;  
          75.         }  
          76.     }  
          77. }  

          對于上下文的入口構建:

          1. //開啟上下文  
          2. using (ContextModule.ContextRuntime.BeginContextRuntime())  
          3. {  
          4.      
          5. }  

          通過Using的方式我們開始上下文生命周期。

          5. 上下文活動對象

          上下文對象的綁定需要延后,不能在對象的構建時就創建上下文。

          使用后期綁定動態的切入到執行的上下文中。

          調用代碼,上下文入口:

          1. /*** 
          2.  * author:深度訓練 
          3.  * blog:http://wangqingpei557.blog.51cto.com/ 
          4.  * **/  
          5. using System;  
          6. using System.Collections.Generic;  
          7. using System.Text;  
          8. using System.Data;  
          9. using ConsoleApplication1.BLL;  
          10. using ConsoleApplication1.Model;  
          11.   
          12. namespace ConsoleApplication1  
          13. {  
          14.     public class Program  
          15.     {  
          16.         public static void Main(string[] args)  
          17.         {  
          18.             BLL.BLL_Order order = new BLL.BLL_Order();  
          19.             using (ContextModule.ContextRuntime.BeginContextRuntime())  
          20.             {  
          21.                 Model.Model_Order ordermodel = new Model_Order() { OrderGuid = Guid.NewGuid(), OrderTime = DateTime.Now };  
          22.                 Model.Model_Order resultmodel = ContextModule.ContextAction.PostMethod<BLL.BLL_Order, Model.Model_Order>(order, order.GetMethodInfo("InsertOrderSingle"), ordermodel);  
          23.                 ContextModule.ContextAction.PostMethod<BLL.BLL_Order, object>(order, order.GetMethodInfo("SendOrder"), ordermodel);  
          24.             }  
          25.   
          26.         }  
          27.     }  
          28. }  

          6. 上下文在分層架構中的運用

          有了上下文的核心原型之后我們可以擴展到分層架構中來,對于分層架構的使用其實很有必要,一般的大型業務系統都是混合的使用模式,可能有C/SB/SMobile終端等等。

          對于加入Service層之后BLLDAL將位于服務之后,對于來自客戶端的調用需要經過一些列的身份驗證及權限授予。有了WCF之后面向SOA的架構開發變的相對容易點,對安全、性能、負載等等都很完美,所以大部分的情況下我們很少需要控制BLLDAL的執行運行。

          那么沒有使用WCF構建分布式的系統時或者是沒有分布式的需求就是直接的調用,如WEB的一般開發,從UIBLLDAL。或者是普通的Winfrom的項目、控制臺項目屬于內網的使用,可能就需要控制到代碼的執行。

          下面我通過演示一個具體的實例來看看到底效果如何。

          我以控制臺的程序作為演示項目類型,也使用簡單的三層架構。



          這個再簡單不過了吧,為了演示越簡單越好,關鍵是突出重點。

          需求:

          DAL對象里面加入一個插入Order實體對象的方法:

          1. /*** 
          2.  * author:深度訓練 
          3.  * blog:http://wangqingpei557.blog.51cto.com/ 
          4.  * **/  
          5. using System;  
          6. using System.Collections.Generic;  
          7. using System.Text;  
          8.   
          9. namespace ConsoleApplication1.DAL  
          10. {  
          11.     [ContextModule.ContextEveningBound(IsEvening = true)]  
          12.     public class DAL_Order : ContextModule.ContextModuleBaseObject<DAL_Order>  
          13.     {  
          14.         [ContextModule.ContextLogHandler(OperationSort = 1)]  
          15.         [ContextModule.ContextSecurityHanlder(OperationSort = 2)]  
          16.         public Model.Model_Order InsertOrderSingle(Model.Model_Order ordermodel)  
          17.         {  
          18.             return new Model.Model_Order() { OrderGuid = Guid.NewGuid(), OrderTime = DateTime.Now };  
          19.         }  
          20.     }  
          21. }  


           

          在這個類的上面有一個特性ContextEveningBound,該是用來表示當前對象屬于后期綁定到上下文的對象。同時該類也繼承自一個ContextModuleBaseObject<DAL_Order>泛型類,主要作用是將對象強制的綁定到上下文進行管理。
          在方法InsertOrderSingle上面有兩個特性,ContextLogHandler是用來記錄方法的執行日志,ContextSecurityHanlder是用來在方法執行的過程中強制要求管理員認證。
          BLL對象代碼:
          1. /*** 
          2.  * author:深度訓練 
          3.  * blog:http://wangqingpei557.blog.51cto.com/ 
          4.  * **/  
          5. using System;  
          6. using System.Collections.Generic;  
          7. using System.Text;  
          8. using System.Reflection;  
          9.   
          10. namespace ConsoleApplication1.BLL  
          11. {  
          12.     [ContextModule.ContextEveningBound(IsEvening = true)]  
          13.     public class BLL_Order : ContextModule.ContextModuleBaseObject<BLL_Order>  
          14.     {  
          15.         DAL.DAL_Order dal_order = new DAL.DAL_Order();  
          16.   
          17.         [ContextModule.ContextExceptionHandler(OperationSort = 1)]  
          18.         public Model.Model_Order InsertOrderSingle(Model.Model_Order ordermodel)  
          19.         {  
          20.             return ContextModule.ContextAction.PostMethod<DAL.DAL_Order, Model.Model_Order>(  
          21.                 dal_order, dal_order.GetMethodInfo("InsertOrderSingle"), ordermodel);  
          22.         }  
          23.     }  
          24. }  


           

          在BLL對象里面有一個調用DAL對象方法的實例對象,為了演示簡單這里沒有加入層的依賴注入設計方案,通過直接調 用方式。在BLL方法體中有一個專門用來在上下文中調用方法的接口,這是約束目的是為了能讓框架切入到方法的執行之前先執行。具體的設計原理我將在下一篇 文章中詳細講解。
          在方法的上面有一個ContextExceptionHandler特性,目的是安全的調用DAL對象的方法,在有異常的情況下能通過上下文的方式人性化的提示錯誤信息。這樣我們就不需要頻繁的編寫捕獲異常的代碼,看起來也不爽,我們要的是代碼的整潔、美麗。
          UI調用:
          1. /*** 
          2.  * author:深度訓練 
          3.  * blog:http://wangqingpei557.blog.51cto.com/ 
          4.  * **/  
          5. using System;  
          6. using System.Collections.Generic;  
          7. using System.Text;  
          8. using System.Data;  
          9. using ConsoleApplication1.BLL;  
          10. using ConsoleApplication1.Model;  
          11.   
          12. namespace ConsoleApplication1  
          13. {  
          14.     public class Program  
          15.     {  
          16.         public static void Main(string[] args)  
          17.         {  
          18.             BLL.BLL_Order order = new BLL.BLL_Order();  
          19.             //開啟上下文  
          20.             using (ContextModule.ContextRuntime.BeginContextRuntime())  
          21.             {  
          22.                 Model.Model_Order ordermodel = new Model_Order() { OrderGuid = Guid.NewGuid(), OrderTime = DateTime.Now };  
          23.   
          24.                 Model.Model_Order resultmodel =  
          25.                     ContextModule.ContextAction.PostMethod<BLL.BLL_Order, Model.Model_Order>(  
          26.                     order, order.GetMethodInfo("InsertOrderSingle"), ordermodel);  
          27.             }  
          28.   
          29.         }  
          30.     }  
          31. }  

          執行效果:


          會先執行日志的記錄,然后要求我們輸入用戶憑證才能繼續執行下面的方法。

          我輸入YES才能繼續執行插入的方法。我們可以通過很簡單的實現上下文的管理接口,對方法進行控制。
          總結:該篇文章只是介紹上下文的作用、原理、優勢。下篇文章:“.NET 面向上下文架構模式(實現)”將詳細的介紹上下文框架如何開發。[王清培版權所有,轉載請給出署名]

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 夹江县| 元谋县| 东台市| 温宿县| 富蕴县| 昆明市| 濮阳县| 和政县| 无锡市| 阳朔县| 清新县| 且末县| 洛扎县| 襄城县| 蓬溪县| 新丰县| 朝阳区| 舟曲县| 福贡县| 叙永县| 柘荣县| 土默特右旗| 连平县| 柳州市| 定襄县| 那坡县| 东乡| 商丘市| 大厂| 巴林右旗| 习水县| 奉化市| 德江县| 泽州县| 定陶县| 修文县| 且末县| 景宁| 洛川县| 西吉县| 体育|