海水正藍

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

          1. 上下文概述

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

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

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

          在Remoting中跨AppDomin訪問也是建立在上下文基礎(chǔ)上的,請求的消息通過隧道后序列化到達調(diào)用發(fā)。王清培版權(quán)所有,轉(zhuǎn)載請給出署名

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

          那么就讓我們來領(lǐng)略一下上下文的奧秘吧!

          2. 上下文的一般應(yīng)用

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

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

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

          這么多的優(yōu)勢存在,看來我們是有必要嘗試一下這中設(shè)計模式了。那么就目前系統(tǒng)開發(fā)框架而言我們的上下文能用在哪里呢?我想當務(wù)之急就是將分層架構(gòu)中的所有單條線上的對象進行上下文管理。[王清培版權(quán)所有,轉(zhuǎn)載請給出署名]

          典型的三層架構(gòu):

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

           

          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的執(zhí)行代碼:

           

          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("訂單發(fā)送成功!");  
          25.          }  
          26.      }  
          27.  }  

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

          3. 上下文共享區(qū)域

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

          BLL調(diào)用代碼:

          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執(zhí)行代碼:DAL執(zhí)行代碼:DAL執(zhí)行代碼:DAL執(zhí)行代碼:

          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. 上下文運行時環(huán)境

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

          上下文構(gòu)建:


          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.     /// 上下文運行時環(huán)境。  
          13.     /// 上下文邏輯運行時環(huán)境,環(huán)境中的功能都是可以通過附加進來的。  
          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.         /// 獲取運行時創(chuàng)建上下文的時間  
          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.         /// 獲取運行時創(chuàng)建上下文的唯一標識  
          39.         /// </summary>  
          40.         public virtual Guid InitPrimaryKey { get { return _initPrimaryKey; } }  
          41.         /// <summary>  
          42.         /// 獲取上下文共享區(qū)域中的數(shù)據(jù)  
          43.         /// </summary>  
          44.         /// <param name="key">數(shù)據(jù)Key</param>  
          45.         /// <returns>object數(shù)據(jù)對象</returns>  
          46.         public virtual object GetValue(object key)  
          47.         {  
          48.             return _runTimeResource[key];  
          49.         }  
          50.         /// <summary>  
          51.         /// 設(shè)置上下文共享區(qū)域中的數(shù)據(jù)  
          52.         /// </summary>  
          53.         /// <param name="key">數(shù)據(jù)Key</param>  
          54.         /// <param name="value">要設(shè)置的數(shù)據(jù)對象</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.             //可以通過配置文件配置上下文運行時環(huán)境的參數(shù)。這里只是實現(xiàn)簡單的模擬。  
          73.             _currentContextRuntime = new ContextRuntime();  
          74.             return _currentContextRuntime;  
          75.         }  
          76.     }  
          77. }  

          對于上下文的入口構(gòu)建:

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

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

          5. 上下文活動對象

          上下文對象的綁定需要延后,不能在對象的構(gòu)建時就創(chuàng)建上下文。

          使用后期綁定動態(tài)的切入到執(zhí)行的上下文中。

          調(diào)用代碼,上下文入口:

          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. 上下文在分層架構(gòu)中的運用

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

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

          那么沒有使用WCF構(gòu)建分布式的系統(tǒng)時或者是沒有分布式的需求就是直接的調(diào)用,如WEB的一般開發(fā),從UIBLLDAL。或者是普通的Winfrom的項目、控制臺項目屬于內(nèi)網(wǎng)的使用,可能就需要控制到代碼的執(zhí)行。

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

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



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

          需求:

          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是用來記錄方法的執(zhí)行日志,ContextSecurityHanlder是用來在方法執(zhí)行的過程中強制要求管理員認證。
          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對象里面有一個調(diào)用DAL對象方法的實例對象,為了演示簡單這里沒有加入層的依賴注入設(shè)計方案,通過直接調(diào) 用方式。在BLL方法體中有一個專門用來在上下文中調(diào)用方法的接口,這是約束目的是為了能讓框架切入到方法的執(zhí)行之前先執(zhí)行。具體的設(shè)計原理我將在下一篇 文章中詳細講解。
          在方法的上面有一個ContextExceptionHandler特性,目的是安全的調(diào)用DAL對象的方法,在有異常的情況下能通過上下文的方式人性化的提示錯誤信息。這樣我們就不需要頻繁的編寫捕獲異常的代碼,看起來也不爽,我們要的是代碼的整潔、美麗。
          UI調(diào)用:
          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. }  

          執(zhí)行效果:


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

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

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


          網(wǎng)站導航:
           
          主站蜘蛛池模板: 溧阳市| 三穗县| 曲松县| 浦江县| 临高县| 油尖旺区| 错那县| 资源县| 南郑县| 砀山县| 久治县| 白城市| 多伦县| 大悟县| 洛扎县| 保靖县| 梁河县| 白银市| 吴忠市| 周至县| 日土县| 普兰县| 盐亭县| 射洪县| 沛县| 云林县| 买车| 开远市| 耒阳市| 辉南县| 平塘县| 呼伦贝尔市| 南江县| 南华县| 天镇县| 南陵县| 中江县| 伊宁县| 曲沃县| 梨树县| 建湖县|