日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
.NET面向上下文、AOP架構(gòu)模式(實(shí)現(xiàn))

1.上下文Context、面向切面編程AOP模型分析

桂林網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)公司,桂林網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為桂林近1000家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站制作要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的桂林做網(wǎng)站的公司定做!

在本人的.NET面向上下文、AOP架構(gòu)模式(概述)一文中,我們大概了解了上下文如何輔助對(duì)象在運(yùn)行時(shí)的管理。在很多時(shí)候我們急需在運(yùn)行時(shí)能把對(duì)象控制在一定的邏輯范圍內(nèi),在必要的時(shí)候能讓他們體現(xiàn)出集中化的概念,如人群、車輛、動(dòng)物等等。而Context與AOP有著密切的聯(lián)系,Context表示邏輯抽象的范圍而AOP描述了在這個(gè)邏輯范圍內(nèi)如何進(jìn)行控制。其實(shí)這兩者都是設(shè)計(jì)模式外的設(shè)計(jì)模式,與具體的技術(shù)實(shí)現(xiàn)無關(guān)。

那么Context與AOP兩者在邏輯上是一個(gè)怎樣的概念呢?似乎只有圖才能最貼切的表達(dá)人的理解思路。下圖展現(xiàn)Context與AOP緊密合作的概念模型。

Context圖:1

對(duì)象在運(yùn)行時(shí)被上下文管理,在上下文中可以很方便的獲取到所有的受管理的對(duì)象,這為后面的AOP做了鋪墊。只有Context啟動(dòng)后AOP管理器的爪子才能伸進(jìn)對(duì)象的運(yùn)行時(shí)內(nèi)部與AOP的連接點(diǎn)建立起通訊關(guān)系,才能真正的使對(duì)象能面向切面成功。

在模型圖中,Context中心負(fù)責(zé)對(duì)所有Object進(jìn)行管理,而Object體現(xiàn)出多面性屬性、多面性行為都將包括多面性的特點(diǎn),通過與AOP管理器進(jìn)行連接將控制對(duì)象的運(yùn)行時(shí)行為。

AOP圖:2

通過合理的約定對(duì)象的AOP抽象接口,盡可能的***化將控制權(quán)移動(dòng)到客戶所實(shí)現(xiàn)的“面”中去。比如對(duì)某類方法的調(diào)用,可能需要盡可能的控制方法的所有執(zhí)行權(quán)。所以對(duì)具體的抽象定義有很大的難度。

在上圖中,我們通過AOP核心管理器與對(duì)象的“面”連接上,根據(jù)具體的“面”類型進(jìn)行動(dòng)態(tài)調(diào)用,比如屬性,可能需要在運(yùn)行時(shí)根據(jù)業(yè)務(wù)環(huán)節(jié)進(jìn)行呈現(xiàn)、動(dòng)態(tài)綁定等等,都可以通過AOP去實(shí)現(xiàn)。對(duì)于方法,可能在面向SOA的架構(gòu)中需要記錄下當(dāng)前客戶端的調(diào)用信息,還有一些獨(dú)特的業(yè)務(wù)認(rèn)證等等。不同的 “面”需要進(jìn)行邏輯抽象,這也符合面向?qū)ο蟮脑O(shè)計(jì)原則。很多時(shí)候我們需要先“約定”而不是盡可能的提供擴(kuò)展的機(jī)制,擴(kuò)展點(diǎn)越多系統(tǒng)的復(fù)雜程度就越大,相對(duì)也就難以控制。

2.上下文的實(shí)現(xiàn)

對(duì)上下文、AOP模型我們大致分析了一下,通過模型圖也很形象的體現(xiàn)出上下文、AOP的主要的工作原理。下面我們來通過具體的分析來搭建物理的代碼模型。

面向?qū)ο笫菍?duì)抽象的邏輯模型進(jìn)行物理性的建模,能否真正的體現(xiàn)出模型,需要我們細(xì)心的分析才行。

2.1上下文模型實(shí)現(xiàn)

我們對(duì)上下文模型進(jìn)行抽象實(shí)現(xiàn)為代碼模型。那么我們需要一個(gè)邏輯上代表上下文的對(duì)象,在這里我將它命名為ContextRuntime,上下文的生命周期控制在Using()語句的代碼段中,那么ContextRuntime需要實(shí)現(xiàn)Idisposable接口,讓Using()語句能起作用。

   
 
 
 
  1. using (ContextModule.ContextRuntime.BeginContextRuntime())
  2. {   //上下文的生命周期
  3. }

為什么要這樣設(shè)計(jì)上下文的生命周期呢,這樣設(shè)計(jì)是最為靈活的。在諸如很多微軟的內(nèi)部上下文生命周期的入口也是這樣設(shè)計(jì)的,最經(jīng)典的就是System.Transaction事務(wù)處理。

當(dāng)Using()代碼段結(jié)束后,我們需要釋放當(dāng)前上下文實(shí)例,所以我們需要完成IDisposable接口的實(shí)現(xiàn)。

   
 
 
 
  1. void IDisposable.Dispose()
  2. {
  3. _currentContextRuntime = null;
  4. }

_currentContextRuntime表示上下文對(duì)象實(shí)例的全局私有對(duì)象。

由于多線程應(yīng)用框架的入口點(diǎn)不是我們所能控制的,所以在使用上下文模式的時(shí)候需要使用線程本地存儲(chǔ)解決線程不安全訪問的問題。

[ThreadStatic]

private static ContextRuntime _currentContextRuntime;

我們看一下全部的ContextRuntime對(duì)象代碼:

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

這里只為了實(shí)現(xiàn)基本的模型原型,不會(huì)涉及太多的功能。上下文主要是在當(dāng)前線程中開啟,然后保持在靜態(tài)對(duì)象的多線程安全訪問,***就是對(duì)象的穩(wěn)定釋放。

#p#

2.2上下文對(duì)象綁定實(shí)現(xiàn)

有了上下文之后,如何才能使對(duì)象在運(yùn)行時(shí)動(dòng)態(tài)的綁定到上下文中來。這個(gè)需要在前期編碼的時(shí)候就確定對(duì)象是否要綁定到當(dāng)前上下文以便進(jìn)行管理。

那么我們需要對(duì)客戶使用的對(duì)象進(jìn)行一個(gè)抽象,讓所有需要綁定的對(duì)象實(shí)現(xiàn)我們高層定義的抽象。這里我將命名為ContextModuleBaseObject,由于需要向AOP提供對(duì)象的“面”的連接點(diǎn),所以我們需要在運(yùn)行時(shí)反射獲取到綁定對(duì)象的一些基本信息,如:屬性的“面”、行為的“面”、包括對(duì)象本身的“面”,這些面我們需要將其對(duì)應(yīng)關(guān)系建立起來才能讓后面的AOP起作用。

所以我們將ContextModuleBaseObject定義為泛型類,并且需要加上Class的約束。對(duì)于綁定的對(duì)象在運(yùn)行時(shí)一旦進(jìn)入上下文的生命周期管理,就需要靈活的表示為ContextRuntime對(duì)象,這樣設(shè)計(jì)符合上下文一視同仁的觀念,更便于ContextModuleBaseObject對(duì)象在運(yùn)行期動(dòng)態(tài)的使用上下文的內(nèi)部存儲(chǔ)區(qū)域。

這里我們需要將ContextModuleBaseObject對(duì)象繼承自ContextRuntime對(duì)象。使用經(jīng)典的裝飾者模式,讓ContextModuleBaseObject對(duì)象使用ContextRuntime行為。

 
 
 
 
  1. View Code 
  2. /***
  3.  * author:深度訓(xùn)練
  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. namespace ContextModule
  11. {
  12.     /// 
  13.     /// 上下綁定基類,強(qiáng)制派生類綁定到上下文。
  14.     /// 邏輯上下文的策略構(gòu)造都在這里進(jìn)行。
  15.     /// 
  16.     /// 受管理的上下文綁定對(duì)象類型,通常是ContextModuleBaseObject派生類。
  17.     public class ContextModuleBaseObject : ContextRuntime where T : class
  18.     {
  19.         /// 
  20.         /// 當(dāng)前上下文綁定對(duì)象所綁定到的上下文物理對(duì)象實(shí)例。
  21.         /// 
  22.         private ContextRuntime _contextRunTime;
  23.         public ContextModuleBaseObject()
  24.         {
  25.             if (typeof(T).GetCustomAttributes(typeof(ContextEveningBoundAttribute), false) != null)
  26.             {
  27.                 _IsEvening = true;
  28.                 return;
  29.             }
  30.             //前期靜態(tài)綁定上下文
  31.             if (ContextRuntime.CurrentContextRuntime == null)
  32.                 throw new Exception("上下文環(huán)境未能初始化,請(qǐng)檢查您的代碼入口是否啟用了ContextRuntime對(duì)象。");
  33.             _contextRunTime = ContextRuntime.CurrentContextRuntime;
  34.             _InitContextHandler();
  35.         }
  36.         /// 
  37.         /// 構(gòu)造上下文的類過濾器、方法過濾器映射表。
  38.         /// 
  39.         private void _InitContextHandler() where ChildType : class
  40.         {
  41.             //構(gòu)造類過濾器
  42.             ContextOperationBaseAttribute[] classattr =
  43.                 typeof(ChildType).GetCustomAttributes(typeof(ContextOperationBaseAttribute), false) as ContextOperationBaseAttribute[];
  44.             if (classattr.Length > 0)
  45.             {
  46.                 ContextOperationBaseAttribute joinoper = _JoinOperation(classattr);
  47.                 _contextRunTime.FilterMap.MapOperation(typeof(T).FullName, joinoper);
  48.             }
  49.             //構(gòu)造方法過濾器
  50.             foreach (MethodInfo method in typeof(ChildType).GetMethods())
  51.             {
  52.                 ContextOperationBaseAttribute[] methodattr =
  53.                     method.GetCustomAttributes(typeof(ContextOperationBaseAttribute), false) as ContextOperationBaseAttribute[];
  54.                 if (methodattr.Length <= 0)
  55.                     continue;
  56.                 ContextOperationBaseAttribute joinoper = _JoinOperation(methodattr);
  57.                 _contextRunTime.FilterMap.MapOperation(string.Format("{0}.{1}", method.DeclaringType.FullName, method.Name), joinoper);
  58.             }
  59.         }
  60.         internal bool _IsEvening { get; set; }
  61.         /// 
  62.         /// 后期動(dòng)態(tài)綁定上下文。
  63.         /// 
  64.         internal void _EveningBoundChildClass() where ChildType : class
  65.         {
  66.             if (_contextRunTime != null)
  67.                 return;//說明之前已經(jīng)進(jìn)行過動(dòng)態(tài)調(diào)用
  68.             _contextRunTime = ContextRuntime.CurrentContextRuntime;//動(dòng)態(tài)綁定當(dāng)前運(yùn)行時(shí)上下文
  69.             _InitContextHandler();
  70.         }
  71.         private ContextOperationBaseAttribute _JoinOperation(ContextOperationBaseAttribute[] operationarray)
  72.         {
  73.             //必須對(duì)數(shù)組進(jìn)行排序后才能連接
  74.             for (int i = 0; i < operationarray.Length; i++)
  75.             {
  76.                 for (int j = 0; j < i; j++)
  77.                 {
  78.                     if (operationarray[j].OperationSort > operationarray[j + 1].OperationSort)
  79.                     {
  80.                         ContextOperationBaseAttribute oper = operationarray[j];
  81.                         operationarray[j] = operationarray[j + 1];
  82.                         operationarray[j + 1] = oper;
  83.                     }
  84.                 }
  85.             }
  86.             ContextOperationBaseAttribute opernext = operationarray[0];
  87.             for (int i = 1; i < operationarray.Length; i++)
  88.             {
  89.                 opernext.NextOperation = operationarray[i];
  90.                 opernext = operationarray[i];//保持對(duì)當(dāng)前循環(huán)對(duì)象的上級(jí)對(duì)象的引用。
  91.             }
  92.             return operationarray[0];
  93.         }
  94.         public MethodInfo GetMethodInfo(string methodname)
  95.         {
  96.             return this.GetType().GetMethod(methodname);
  97.         }
  98.         public override Guid InitPrimaryKey
  99.         {
  100.             get
  101.             {
  102.                 return _contextRunTime.InitPrimaryKey;
  103.             }
  104.         }
  105.         public override DateTime InitTime
  106.         {
  107.             get
  108.             {
  109.                 return _contextRunTime.InitTime;
  110.             }
  111.         }
  112.         public override object GetValue(object key)
  113.         {
  114.             return _contextRunTime.GetValue(key);
  115.         }
  116.         public override void SetValue(object key, object value)
  117.         {
  118.             _contextRunTime.SetValue(key, value);
  119.         }
  120.     }
  121. }

ContextModuleBaseObject 類主要實(shí)現(xiàn)的功能就是將對(duì)象動(dòng)態(tài)的添加到當(dāng)前上下文中。然后為AOP做些輔助性的工作,包括對(duì)類、屬性、行為的特性元數(shù)據(jù)的緩存,這里只實(shí)現(xiàn)了行為的特性緩存??梢愿鶕?jù)自己的需要擴(kuò)展AOP的功能,在對(duì)象的屬性上標(biāo)記特性讓屬性也發(fā)揮作用。這里的特性就是AOP公布的指定接口。

對(duì)_JoinOperation方法的解釋我們留在后面,這里是一個(gè)數(shù)據(jù)結(jié)構(gòu)。將ContextOperationBaseAttribute

類型串成鏈表,讓方法的執(zhí)行穿過所有的ContextOperationBaseAttribute處理類。

#p#

2.3上下文對(duì)象的后期綁定實(shí)現(xiàn)

為了讓綁定對(duì)象支持上下文后期綁定,需要一個(gè)特性作為表示。

 
 
 
 
  1. View Code 
  2. /***
  3.  * author:深度訓(xùn)練
  4.  * blog:http://wangqingpei557.blog.51cto.com/
  5.  * **/
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Text;
  9. namespace ContextModule
  10. {
  11.     /// 
  12.     /// 確定設(shè)置類是否需要后期動(dòng)態(tài)綁定到上下文。
  13.     /// 使用該特性的類將是上下文活躍的,只有在使用的時(shí)候才確定當(dāng)前上下文。
  14.     /// 
  15.     [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
  16.     public class ContextEveningBoundAttribute : Attribute
  17.     {
  18.         public ContextEveningBoundAttribute() { }
  19.         private bool _isEvening;
  20.         /// 
  21.         /// 指定對(duì)象是否需要后期動(dòng)態(tài)綁定上下文。
  22.         /// 
  23.         public bool IsEvening { set { _isEvening = value; } get { return _isEvening; } }
  24.     }
  25. }

僅僅為了標(biāo)識(shí)后期綁定說明。在ContextModuleBaseObject 對(duì)象的構(gòu)造函數(shù)中可以看到。

 
 
 
 
  1. View Code 
  2. public ContextModuleBaseObject()
  3.         {
  4.             if (typeof(T).GetCustomAttributes(typeof(ContextEveningBoundAttribute), false) != null)
  5.             {
  6.                 _IsEvening = true;
  7.                 return;
  8.             }
  9.             //前期靜態(tài)綁定上下文
  10.             if (ContextRuntime.CurrentContextRuntime == null)
  11.                 throw new Exception("上下文環(huán)境未能初始化,請(qǐng)檢查您的代碼入口是否啟用了ContextRuntime對(duì)象。");
  12.             _contextRunTime = ContextRuntime.CurrentContextRuntime;
  13.             _InitContextHandler();
  14.         }

到這里我們已經(jīng)實(shí)現(xiàn)對(duì)象的動(dòng)態(tài)綁定到上下文來,下面我們來分析Context如何用AOP配合完成面向切面編程的機(jī)制。

2.4.AOP中的對(duì)象行為的契約設(shè)計(jì)實(shí)現(xiàn)

其實(shí)這里的契約設(shè)計(jì)也就是圖2中對(duì)AOP中的“面”的約定。

AOP全稱為“面向切面編程”。對(duì)象在運(yùn)行時(shí)具備多個(gè)面,其實(shí)在.NET里面我們習(xí)慣性的用特性(Attribute)來表達(dá)這個(gè)概念。因?yàn)椴恍枰膭?dòng)任何代碼就可以將特性加到對(duì)象中的任何元素中去,在不同的業(yè)務(wù)環(huán)節(jié)或者說是功能環(huán)節(jié)就能動(dòng)態(tài)的轉(zhuǎn)動(dòng)元素體現(xiàn)出“切面”的優(yōu)勢(shì),當(dāng)然具體的實(shí)現(xiàn)可能很多種,這里使用特性來完成。

在此約定任何處理對(duì)象方法的“面”都將被抽象。這里我將命名為ContextOperationBaseAttribute該特性表示所有附加到方法上的特性的基類,對(duì)“面”的抽象。

那么不同類型的面將有著不同的操作行為,比如:記錄日志的特性、計(jì)算性能的特性、認(rèn)證安全的特性他們都有著不同的行為和屬性,所以這里我們還需要提取一個(gè)頂層接口作為行為類的特性處理抽象。這里我將命名為IContextOperationHandler該接口作為統(tǒng)一執(zhí)行行為特性的高層依賴。其實(shí)這里也體現(xiàn)出依賴倒置原則,依賴抽象不依賴具體實(shí)現(xiàn)。

完整的ContextOperationBaseAttribute類:

 
 
 
 
  1. View Code 
  2. /***
  3.  * author:深度訓(xùn)練
  4.  * blog:http://wangqingpei557.blog.51cto.com/
  5.  * **/
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Text;
  9. namespace ContextModule
  10. {
  11.     /// 
  12.     /// 上下文操作動(dòng)作特性化基類。
  13.     /// 所有對(duì)上下文中的類、方法的過濾操作都必須繼承此類。
  14.     /// 
  15.     public abstract class ContextOperationBaseAttribute : Attribute, IContextOperationHandler
  16.     {
  17.         /// 
  18.         /// 過濾器的處理順序,從小到大的方式進(jìn)行處理。
  19.         /// 
  20.         public int OperationSort { get; set; }
  21.         /// 
  22.         /// 下一次過濾操作類
  23.         /// 
  24.         internal ContextOperationBaseAttribute NextOperation { get; set; }
  25.         /// 
  26.         /// 開始處理過濾對(duì)象
  27.         /// 
  28.         /// 方法的返回值類型
  29.         /// 調(diào)用的方法包裝
  30.         /// 方法的有序參數(shù)
  31.         /// 
  32.         public virtual Result ResultAction(ContextMethodInfo actionmethod, params object[] paramarray)
  33.         {
  34.             object result = null;
  35.             if (!actionmethod.IsPost)
  36.             {
  37.                 result = (this as IContextOperationHandler).Operation(actionmethod, paramarray);
  38.                 if (this.NextOperation != null)
  39.                     return this.NextOperation.ResultAction(actionmethod, paramarray);
  40.             }
  41.             if (result != null)
  42.                 return (Result)result;
  43.             return default(Result);
  44.         }
  45.         public abstract object Operation(ContextMethodInfo contextmethod, params object[] paramarray);
  46.     }
  47. }

作為抽象的頂層類需要完成派生類重復(fù)的勞動(dòng)。這里實(shí)現(xiàn)了一個(gè)ResultAction泛型方法,該方法是外部調(diào)用綁定對(duì)象的方法時(shí)的入口點(diǎn)。但是具體的實(shí)現(xiàn)區(qū)別在于IContextOperationHandler 接口的定義。

由于行為的特性可能存在多個(gè),所以對(duì)于***一個(gè)處理完的特性需要結(jié)束整個(gè)的調(diào)用鏈表,并且返回值。在ResultAction虛方法里面對(duì)IContextOperationHandler 接口的Operation方法執(zhí)行調(diào)用,該方法將會(huì)在實(shí)現(xiàn)特定行為特性里面實(shí)現(xiàn),這里又體現(xiàn)出“模板方法”設(shè)計(jì)模式。在抽象類中約定行為,在派生類中實(shí)現(xiàn)具體。

這里比較有意思的是,特性不在像大家實(shí)現(xiàn)ORM的那中簡單的標(biāo)識(shí)了。其實(shí)特性真正強(qiáng)大的地方在于運(yùn)行時(shí)能動(dòng)態(tài)的獲取到,這得益于.NET元數(shù)據(jù)的功勞。并且動(dòng)態(tài)實(shí)例化然后當(dāng)作普通的對(duì)象實(shí)例使用。這個(gè)觀念很多.NET程序員不宜轉(zhuǎn)變。

在這里的ContextOperationBaseAttribute又描述了另外一種數(shù)據(jù)結(jié)構(gòu)“單向鏈表”,為了將綁定對(duì)象的行為***化的在特性中實(shí)現(xiàn),我們將方法的調(diào)用完全的傳遞到實(shí)現(xiàn)特性中去。那么對(duì)方法上多個(gè)作用的特性如何穿過呢,并且能保證數(shù)據(jù)的正常傳遞和返回。有兩點(diǎn)我們需要注意,一個(gè)是特性的作用順序,二個(gè)是特性對(duì)方法的執(zhí)行是否完成。這兩點(diǎn)我們都要考慮進(jìn)去,所以在ContextOperationBaseAttribute類中用public int OperationSort { get; set; }屬性表示特性的執(zhí)行順序,記錄日志的特性和計(jì)算性能的特性我們很難在這里定死,需要根據(jù)后期程序的執(zhí)行情況而定,如我要先記錄日志然后在執(zhí)行方法。

那么我們又如何將ContextOperationBaseAttribute類型串聯(lián)起來呢?在ContextModuleBaseObject

泛型綁定類中我們?cè)跇?gòu)造的時(shí)候就將通過ContextOperationBaseAttribute. OperationSort屬性初始化了特性處理鏈表。

那么我們?nèi)绾螌⒕唧w的對(duì)象與特性關(guān)聯(lián)建立起對(duì)應(yīng)關(guān)系呢?一個(gè)行為可能有多個(gè)ContextOperationBaseAttribute的實(shí)現(xiàn)。所以這里我們需要一個(gè)能滿足行為與特性之間的數(shù)據(jù)結(jié)構(gòu)。

這里我將它定義為ContextFilterHandlerMap該類繼承自Dictionary泛型字典類,使用KEY—VALUE的方式存放行為與ContextOperationBaseAttribute處理特性的對(duì)應(yīng)關(guān)系。

 
 
 
 
  1. View Code 
  2. /***
  3.  * author:深度訓(xùn)練
  4.  * blog:http://wangqingpei557.blog.51cto.com/
  5.  * **/
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Text;
  9. namespace ContextModule
  10. {
  11.     /// 
  12.     /// 特定于上下文的過濾器映射表。
  13.     /// 上下文中的任何方法如果需要進(jìn)行上下文管理的,則使用ContextModule.ContextOperationBaseAttribute特性派生類進(jìn)行管理。
  14.     /// 所有附加于方法、類上的特性管理類都將被映射到ContextModule.ContextFilterHandlerMap實(shí)例中。
  15.     /// 
  16.     public class ContextFilterHandlerMap : Dictionary
  17.     {
  18.         public ContextFilterHandlerMap() { }
  19.         /// 
  20.         /// 獲取方法對(duì)應(yīng)的過濾器處理特性
  21.         /// 
  22.         /// 映射Key
  23.         /// ContextOperationBaseAttribute特性實(shí)例
  24.         public ContextOperationBaseAttribute MapOperation(string mapname)
  25.         {
  26.             return this[mapname];
  27.         }
  28.         /// 
  29.         /// 設(shè)置過濾器與特定方法的映射
  30.         /// 
  31.         /// 映射Key
  32.         /// 過濾器特性基類ContextOperationBaseAttribute
  33.         public void MapOperation(string mapname, ContextOperationBaseAttribute operationlist)
  34.         {
  35.             this.Add(mapname, operationlist);
  36.         }
  37.     }
  38. }

***只需要向外提供IContextOperationHandler接口就可以實(shí)現(xiàn)方法與處理特性的串聯(lián)了。

 
 
 
 
  1. View Code 
  2. /***
  3.  * author:深度訓(xùn)練
  4.  * blog:http://wangqingpei557.blog.51cto.com/
  5.  * **/
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Text;
  9. using System.IO;
  10. namespace ContextModule
  11. {
  12.     /// 
  13.     /// 上下文操作管理接口
  14.     /// 
  15.     public interface IContextOperationHandler
  16.     {
  17.         /// 
  18.         /// 開始上下文處理
  19.         /// 
  20.         /// CRL目前正在執(zhí)行的上下文方法的信息。
  21.         /// 可以通過ContextMethodInfo實(shí)例獲取方法詳細(xì)信息。
  22.         ///參數(shù)數(shù)組
  23.         object Operation(ContextMethodInfo contextmethod, params object[] paramarray);
  24.     }
  25. }

通過對(duì)外公開接口,讓實(shí)現(xiàn)“面”的客戶端去完成對(duì)具體對(duì)象方法的執(zhí)行。ContextMethodInfo類型是包裝System.Reflection. MethodInfo 方法元數(shù)據(jù)的,將通過調(diào)用切入到方法內(nèi)部這里基本上實(shí)現(xiàn)了AOP對(duì)行為的多面支持,下面我們來看一下如果動(dòng)態(tài)的切入到方法中。

#p#

2.5.動(dòng)態(tài)入口的實(shí)現(xiàn)

對(duì)所有方法的調(diào)用將是比較頭疼的。由于一般面向上下文、面向切面都是有編寫者控制對(duì)方法的調(diào)用,可以很方便的通過后臺(tái)的隱式的調(diào)用。但是作為普通的方法的入口調(diào)用主要有三種方式實(shí)現(xiàn)。

1):委托實(shí)現(xiàn)入口

通過使用System.Delegate動(dòng)態(tài)派生類型來完成對(duì)方法的調(diào)用,但是委托對(duì)于方法的簽名必須是強(qiáng)類型的,所以很難做到通用的調(diào)用入口。

2):反射實(shí)現(xiàn)入口(通過擴(kuò)展方法在OBJECT基類中加入獲取MethodInfo對(duì)象的方法,使用時(shí)通過該方法獲取調(diào)用方法的信息)

通過擴(kuò)展方法在System.Object中加入一個(gè)擴(kuò)展方法用來獲取調(diào)用方法的信息,然后通過反射動(dòng)態(tài)的調(diào)用,這種方法只比較常用的。但是如何框架是在.NET2.0中使用的擴(kuò)展方法還不能實(shí)現(xiàn),這里我是在ContextModuleBaseObject基類中加了一個(gè)類似擴(kuò)展方法的方式。綁定對(duì)象可以很方便的獲取到調(diào)用方法的MethodInfo對(duì)象。

3):***的動(dòng)態(tài)編譯(向抽象、多態(tài)敬禮)
分享題目:.NET面向上下文、AOP架構(gòu)模式(實(shí)現(xiàn))
網(wǎng)站鏈接:http://www.5511xx.com/article/ccocdjj.html