您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關如何理解.NET面向上下文架構模式,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
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的調用代碼:
View Code /*** * author:深度訓練 * blog:http://wangqingpei557.blog.51cto.com/ * **/ using System; using System.Collections.Generic; using System.Text; using System.Reflection; namespace ConsoleApplication1.BLL { [ContextModule.ContextEveningBound(IsEvening = true)] public class BLL_Order : ContextModule.ContextModuleBaseObject<BLL_Order> { DAL.DAL_Order dal_order = new DAL.DAL_Order(); [ContextModule.ContextExceptionHandler(OperationSort = 1)] public Model.Model_Order InsertOrderSingle(Model.Model_Order ordermodel) { return ContextModule.ContextAction.PostMethod<DAL.DAL_Order, Model.Model_Order>( dal_order, dal_order.GetMethodInfo("InsertOrderSingle"), ordermodel); } [ContextModule.ContextExceptionHandler(OperationSort = 1)] public void SendOrder(Model.Model_Order ordermodel) { ContextModule.ContextAction.PostMethod<DAL.DAL_Order, object>( dal_order, dal_order.GetMethodInfo("SendOrder"), ordermodel); } } }
DAL的執行代碼:
View Code /*** * author:深度訓練 * blog:http://wangqingpei557.blog.51cto.com/ * **/ using System; using System.Collections.Generic; using System.Text; namespace ConsoleApplication1.DAL { [ContextModule.ContextEveningBound(IsEvening = true)] public class DAL_Order : ContextModule.ContextModuleBaseObject<DAL_Order> { [ContextModule.ContextLogHandler(OperationSort = 1)] [ContextModule.ContextSecurityHanlder(OperationSort = 2)] public Model.Model_Order InsertOrderSingle(Model.Model_Order ordermodel) { return new Model.Model_Order() { OrderGuid = Guid.NewGuid(), OrderTime = DateTime.Now }; } [ContextModule.ContextLogHandler(OperationSort = 1)] public void SendOrder(Model.Model_Order ordermodel) { Console.WriteLine("訂單發送成功!"); } } }
上述代碼是我模擬一個上下文的執行過程。
3. 上下文共享區域
在每個獨立的上下文環境中應該有一片共享的數據存儲區域,以備多個上下文對象訪問。這種方便性多半存在于項目比較緊張的修改需求的時候或者加新業務的時候擴展方法用的。BLL調用代碼:
View Code [ContextModule.ContextExceptionHandler(OperationSort = 1)] public void UpdateOrderSingle() { Model.Model_Order ordermodel = new Model.Model_Order() { OrderGuid = Guid.NewGuid(), OrderTime = DateTime.Now }; //放入上下文共享對象池 ContextModule.ContextRuntime.CurrentContextRuntime.SetValue("updateorder", ordermodel); ContextModule.ContextAction.PostMethod<DAL.DAL_Order, object>( dal_order, dal_order.GetMethodInfo("UpdateOrderSingle"), null); }
DAL執行代碼:
[ContextModule.ContextLogHandler(OperationSort = 1)] public void UpdateOrderSingle() { Model.Model_Order ordermodel = ContextModule.ContextRuntime.CurrentContextRuntime.GetValue("updateorder") as Model.Model_Order; }
4. 上下文運行時環境
對于上下文運行時環境的構建需要考慮到運行時是共享的上下文對象。對于納入上下文管理的所有對象都需要共享或者說是受控于上下文運行時。
上下文構建:
View Code /*** * author:深度訓練 * blog:http://wangqingpei557.blog.51cto.com/ * **/ using System; using System.Collections.Generic; using System.Text; namespace ContextModule { /// <summary> /// 上下文運行時環境。 /// 上下文邏輯運行時環境,環境中的功能都是可以通過附加進來的。 /// </summary> public class ContextRuntime : IDisposable { #region IDisposable成員 void IDisposable.Dispose() { _currentContextRuntime = null; } #endregion protected ContextRuntime() { } private DateTime _initTime = DateTime.Now; /// <summary> /// 獲取運行時創建上下文的時間 /// </summary> public virtual DateTime InitTime { get { return _initTime; } } private Dictionary<object, object> _runTimeResource = new Dictionary<object, object>(); private ContextFilterHandlerMap _filterMap = new ContextFilterHandlerMap(); /// <summary> /// 獲取上下文中的方法、類過濾器映射表 /// </summary> public ContextFilterHandlerMap FilterMap { get { return _filterMap; } } private Guid _initPrimaryKey = Guid.NewGuid(); /// <summary> /// 獲取運行時創建上下文的唯一標識 /// </summary> public virtual Guid InitPrimaryKey { get { return _initPrimaryKey; } } /// <summary> /// 獲取上下文共享區域中的數據 /// </summary> /// <param name="key">數據Key</param> /// <returns>object數據對象</returns> public virtual object GetValue(object key) { return _runTimeResource[key]; } /// <summary> /// 設置上下文共享區域中的數據 /// </summary> /// <param name="key">數據Key</param> /// <param name="value">要設置的數據對象</param> public virtual void SetValue(object key, object value) { _runTimeResource[key] = value; } [ThreadStatic] private static ContextRuntime _currentContextRuntime; /// <summary> /// 獲取當前上下文運行時對象. /// </summary> public static ContextRuntime CurrentContextRuntime { get { return _currentContextRuntime; } } /// <summary> /// 開始運行時上下文 /// </summary> /// <returns>ContextRuntime</returns> public static ContextRuntime BeginContextRuntime() { //可以通過配置文件配置上下文運行時環境的參數。這里只是實現簡單的模擬。 _currentContextRuntime = new ContextRuntime(); return _currentContextRuntime; } } }
對于上下文的入口構建:
using (ContextModule.ContextRuntime.BeginContextRuntime()) { }
通過Using的方式我們開始上下文生命周期。
5. 上下文活動對象
上下文對象的綁定需要延后,不能在對象的構建時就創建上下文。
使用后期綁定動態的切入到執行的上下文中。
調用代碼,上下文入口:
View Code /*** * author:深度訓練 * blog:http://wangqingpei557.blog.51cto.com/ * **/ using System; using System.Collections.Generic; using System.Text; using System.Data; using ConsoleApplication1.BLL; using ConsoleApplication1.Model; namespace ConsoleApplication1 { public class Program { public static void Main(string[] args) { BLL.BLL_Order order = new BLL.BLL_Order(); using (ContextModule.ContextRuntime.BeginContextRuntime()) { Model.Model_Order ordermodel = new Model_Order() { OrderGuid = Guid.NewGuid(), OrderTime = DateTime.Now }; Model.Model_Order resultmodel = ContextModule.ContextAction.PostMethod<BLL.BLL_Order, Model.Model_Order>(order, order.GetMethodInfo("InsertOrderSingle"), ordermodel); ContextModule.ContextAction.PostMethod<BLL.BLL_Order, object>(order, order.GetMethodInfo("SendOrder"), ordermodel); } } } }
6. 上下文在分層架構中的運用
有了上下文的核心原型之后我們可以擴展到分層架構中來,對于分層架構的使用其實很有必要,一般的大型業務系統都是混合的使用模式,可能有C/S、B/S、Mobile終端等等。
對于加入Service層之后BLL、DAL將位于服務之后,對于來自客戶端的調用需要經過一些列的身份驗證及權限授予。有了WCF之后面向SOA的架構開發變的相對容易點,對安全、性能、負載等等都很完美,所以大部分的情況下我們很少需要控制BLL、DAL的執行運行。
那么沒有使用WCF構建分布式的系統時或者是沒有分布式的需求就是直接的調用,如WEB的一般開發,從UI到BLL到DAL。或者是普通的Winfrom的項目、控制臺項目屬于內網的使用,可能就需要控制到代碼的執行。
下面我通過演示一個具體的實例來看看到底效果如何。
我以控制臺的程序作為演示項目類型,也使用簡單的三層架構。
這個再簡單不過了吧,為了演示越簡單越好,關鍵是突出重點。
需求:
在DAL對象里面加入一個插入Order實體對象的方法:
View Code /*** * author:深度訓練 * blog:http://wangqingpei557.blog.51cto.com/ * **/ using System; using System.Collections.Generic; using System.Text; namespace ConsoleApplication1.DAL { [ContextModule.ContextEveningBound(IsEvening = true)] public class DAL_Order : ContextModule.ContextModuleBaseObject<DAL_Order> { [ContextModule.ContextLogHandler(OperationSort = 1)] [ContextModule.ContextSecurityHanlder(OperationSort = 2)] public Model.Model_Order InsertOrderSingle(Model.Model_Order ordermodel) { return new Model.Model_Order() { OrderGuid = Guid.NewGuid(), OrderTime = DateTime.Now }; } } }
在這個類的上面有一個特性ContextEveningBound,該是用來表示當前對象屬于后期綁定到上下文的對象。同時該類也繼承自一個ContextModuleBaseObject<DAL_Order>泛型類,主要作用是將對象強制的綁定到上下文進行管理。
在方法InsertOrderSingle上面有兩個特性,ContextLogHandler是用來記錄方法的執行日志,ContextSecurityHanlder是用來在方法執行的過程中強制要求管理員認證。
BLL對象代碼:
View Code /*** * author:深度訓練 * blog:http://wangqingpei557.blog.51cto.com/ * **/ using System; using System.Collections.Generic; using System.Text; using System.Reflection; namespace ConsoleApplication1.BLL { [ContextModule.ContextEveningBound(IsEvening = true)] public class BLL_Order : ContextModule.ContextModuleBaseObject<BLL_Order> { DAL.DAL_Order dal_order = new DAL.DAL_Order(); [ContextModule.ContextExceptionHandler(OperationSort = 1)] public Model.Model_Order InsertOrderSingle(Model.Model_Order ordermodel) { return ContextModule.ContextAction.PostMethod<DAL.DAL_Order, Model.Model_Order>( dal_order, dal_order.GetMethodInfo("InsertOrderSingle"), ordermodel); } } }
在BLL對象里面有一個調用DAL對象方法的實例對象,為了演示簡單這里沒有加入層的依賴注入設計方案,通過直接調用方式。在BLL方法體中有一個專門用來在上下文中調用方法的接口,這是約束目的是為了能讓框架切入到方法的執行之前先執行。具體的設計原理我將在下一篇文章中詳細講解。
在方法的上面有一個ContextExceptionHandler特性,目的是安全的調用DAL對象的方法,在有異常的情況下能通過上下文的方式人性化的提示錯誤信息。這樣我們就不需要頻繁的編寫捕獲異常的代碼,看起來也不爽,我們要的是代碼的整潔、美麗。
UI調用:
View Code /*** * author:深度訓練 * blog:http://wangqingpei557.blog.51cto.com/ * **/ using System; using System.Collections.Generic; using System.Text; using System.Data; using ConsoleApplication1.BLL; using ConsoleApplication1.Model; namespace ConsoleApplication1 { public class Program { public static void Main(string[] args) { BLL.BLL_Order order = new BLL.BLL_Order(); //開啟上下文 using (ContextModule.ContextRuntime.BeginContextRuntime()) { Model.Model_Order ordermodel = new Model_Order() { OrderGuid = Guid.NewGuid(), OrderTime = DateTime.Now }; Model.Model_Order resultmodel = ContextModule.ContextAction.PostMethod<BLL.BLL_Order, Model.Model_Order>( order, order.GetMethodInfo("InsertOrderSingle"), ordermodel); } } } }
執行效果:
會先執行日志的記錄,然后要求我們輸入用戶憑證才能繼續執行下面的方法。
我輸入YES才能繼續執行插入的方法。我們可以通過很簡單的實現上下文的管理接口,對方法進行控制。
總結:該篇文章只是介紹上下文的作用、原理、優勢。
上述就是小編為大家分享的如何理解.NET面向上下文架構模式了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。