(轉)C#製做一個消息攔截器

首先,咱們先要製做一個自定義Attribute,讓他能夠具備上下文讀取功能,因此咱們這個Attribute類要同時繼承Attribute和IContextAttribute。函數

接口IContextAttribute中有兩個方法須要實現this

一、bool   IsContextOK(Context ctx, IConstructionCallMessage msg);spa

二、void  GetPropertiesForNewContext(IConstructionCallMessage msg);.net

簡單解釋一下這兩個方法:調試

一、IsContextOK方法是讓咱們檢查當前上下文(current  context)是否有問題,若是沒有問題返回true,有問題的話返回false,而後該類會去調用GetPropertiesForNewContextcode

二、GetPropertiesForNewContext 是 系統會自動new一個context ,而後讓咱們去作些新環境應該作的事。orm

 

[csharp] view plain  copy
 
 print?
  1. /// <summary>  
  2. /// Some class if you want to intercept,you must mark this attribute.  
  3. /// </summary>  
  4. public class InterceptAttribute : Attribute, IContextAttribute  
  5. {  
  6.     public InterceptAttribute()  
  7.     {  
  8.         Console.WriteLine(" Call 'InterceptAttribute' - 'Constructor'  ");  
  9.     }  
  10.     public void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)  
  11.     {  
  12.         ctorMsg.ContextProperties.Add(new InterceptProperty());  
  13.     }  
  14.     public bool IsContextOK(Context ctx, IConstructionCallMessage ctorMsg)  
  15.     {  
  16.         InterceptProperty interceptObject = ctx.GetProperty("Intercept") as InterceptProperty;  
  17.           
  18.         return interceptObject != null;  
  19.     }  
  20. }  

ok,這是這個類的實現,要解釋幾點:對象

 

一、InterceptAttribute這個類繼承的是Attribute,用於[Attribute]標記用的。blog

二、InterceptAttribute這個類繼承IContextAttribute,用於給標記上的類得到上下文權限,而後要實現該接口的兩個方法。繼承

三、IsContextOK方法是去判斷當前是否有「Intercept」這個屬性,由於咱們只須要這個屬性,因此只要檢查這個屬性當前上下文有沒有便可,若是有返回true,沒有的話會調用GetPropertiesForNewContext函數。

(咱們這裏只作攔截器功能,因此只添加Intercept自定義屬性,固然若是有須要能夠添加多個屬性,而後在這個函數中進行相應檢查)

四、若是調用GetPropertiesForNewContext函數,他會讓咱們進行新上下文環境的自定義,我在這作了一個操做:在當前的上下文中添加一個屬性,這個屬性就是Intercept。

五、下一章我會實現InterceptProperty這個類,其實這個類就是一個上下文屬性。

 

 

好了,接着上一篇文章,咱們要實現一個InterceptProperty類。

先講一下,這個類咱們要繼承兩個接口IContextProperty和IContributeObjectSink

IContextProperty:這個接口是說明該類是一個上下文屬性,他其中有兩個方法IsNewContextOK和Freeze

一、Freeze()該方法用來定位被建立的Context的最後位置,通常不用寫入什麼邏輯。

二、IsNewContextOK()這個方法讓咱們檢驗:咱們對當前新Context是否滿意。滿意返回true,不滿意false則會異常,咱們再進行處理。

IContributeObjectSink: 這個接口是是一個消息池,只有繼承這個接口咱們才能接收Object消息。

固然也有IContributeEnvoySink,IContributeClientContextSink,IContributeServerContextSink,這些消息池,能接收不一樣形式的消息,在這裏不過多解釋。

一、IContributeObjectSink 裏面的 GetObjectSink()方法須要咱們去實現,主要做用是獲得一個消息池的對象。

 

好,話很少說,直接貼代碼:

 

[csharp] view plain  copy
 
 print?
  1. //IContributeObjectSink,IContributeEnvoySink,IContributeClientContextSink,IContributeServerContextSink  
  2.     public class InterceptProperty:IContextProperty,IContributeObjectSink  
  3.     {  
  4.         public InterceptProperty()  
  5.         {  
  6.             Console.WriteLine(" Call 'InterceptProperty' - 'Constructor'  ");  
  7.         }  
  8.         public string Name {   
  9.             get  
  10.             {  
  11.                 return "Intercept";  
  12.             }  
  13.         }  
  14.         public void Freeze(Context newContext)  
  15.         {  
  16.   
  17.         }  
  18.         public bool IsNewContextOK(Context newCtx)  
  19.         {  
  20.             var result = newCtx.GetProperty("Intercept");  
  21.             return result!=null;  
  22.             //return false;  
  23.         }  
  24.   
  25.         public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)  
  26.         {  
  27.             InterceptSink interceptSink = new InterceptSink(nextSink);  
  28.             return interceptSink;  
  29.         }  
  30.     }  
 

簡單解釋一下,IsNewContextOK() 函數中,我主要是在當前新的上下文中得到我想要的Intercept屬性,正常狀況下,系統會構造出InterceptProperty對象,GetProperty()函數就是get出Name屬性是否匹配,若是匹配則return true,不然異常。
另外的GetObjectSink方法則是獲得一個InterceptSink的對象,下一節我會實現InterceptSink類。

 

以前爲InterceptAttribute的上下文環境添加了「Intercept」屬性(InterceptProperty),正由於InterceptProperty繼承了IContributeObjectSink,因此咱們要實現GetObjectSink(),繼而咱們要建立一個繼承ImessageSink的類來做爲返回值。

這樣就引起出了InterceptSink類的實現:

 

[csharp] view plain  copy
 
 print?
  1. public class InterceptSink : IMessageSink  
  2.     {  
  3.         private IMessageSink nextSink = null;  
  4.         public IMessageSink NextSink  
  5.         {  
  6.             get { return nextSink; }  
  7.         }  
  8.         public InterceptSink(IMessageSink nextSink)  
  9.         {  
  10.             Console.WriteLine(" Call 'InterceptSink' - 'Constructor'  ");  
  11.             this.nextSink = nextSink;  
  12.         }  
  13.           
  14.         public IMessage SyncProcessMessage(IMessage msg)  
  15.         {  
  16.               
  17.             Console.WriteLine("method_name: " + msg.Properties["__MethodName"].ToString());  
  18.             IMessage returnMsg = nextSink.SyncProcessMessage(msg);  
  19.             return returnMsg;  
  20.         }  
  21.         public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)  
  22.         {  
  23.             return null;  
  24.         }  
  25.     }  

 

核心方法是:SyncProcessMessage(Imessage msg)

傳入參數msg中,咱們能夠找到調用對象方法的相應數據。

 

ok,咱們攔截器基本構造完成,接下來我來告訴你們如何去使用。

注意一個問題,object攔截器咱們要攔截什麼,那麼咱們就要在須要攔截的類上面作手腳了。

首先,建立咱們須要被攔截的類。

而後,咱們再對類進行相應的包裝:

一、該類要標記InterceptAttribute屬性

二、該類要繼承ContextBoundObject,只有繼承ContextBoundObject的類,vs才能知道該類須要訪問Context,這樣標記的InterceptAttribute纔有效。

 

[csharp] view plain  copy
 
 print?
  1. /// <summary>  
  2.     /// If you want to add the interceptpool on this class , the class need to do:  
  3.     /// 一、inherited form ContextBoundObject.  
  4.     /// 二、mark the InterceptAttribute.  
  5.     /// </summary>  
  6.     [Intercept]  
  7.     public class SimonDemo:ContextBoundObject  
  8.     {  
  9.         public SimonDemo()  
  10.         {  
  11.             Console.WriteLine(" Call 'SimonDemo' - 'Constructor'  ");  
  12.         }  
  13.         public void Operate1()  
  14.         {  
  15.             Console.WriteLine("Call 'SimonDemo' - 'Operate1' ");  
  16.         }  
  17.     }  


而後,咱們在Main函數中建立一個該類的對象,並進行調用方法。

 

 

[csharp] view plain  copy
 
 print?
  1. class Program  
  2.    {  
  3.        static void Main(string[] args)  
  4.        {  
  5.            Console.WriteLine("Call Main ..");  
  6.   
  7.            SimonDemo simon = new SimonDemo();  
  8.            simon.Operate1();  
  9.   
  10.            Console.WriteLine("exit Main ..");  
  11.            Console.Read();  
  12.        }  
  13.    }  


這樣,經過調試,咱們就能夠看出攔截器都攔截出了什麼

 

接下來是運行結果:

這樣能夠看出個人程序攔截,並輸出了調用函數的名字。

相關文章
相關標籤/搜索