(转)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.    }  


这样,经过调试,咱们就能够看出拦截器都拦截出了什么

 

接下来是运行结果:

这样能够看出个人程序拦截,并输出了调用函数的名字。

相关文章
相关标签/搜索