• Castle AOP 系列(一):对类方法调用的拦截


    熟悉Castle的朋友一定清楚:在Castle体系中,有一个叫Aspect#的子项目。Aspect#是一个AOP的框架,在这篇文章中,我并不打算直接开始讲Aspect#,因为Aspect#的封装过于完善,不太利于用来讲述AOP的具体实现细节。其实Aspect#的基础是DynamicProxy,所以,我们先来讲讲DynamicProxy。

    在很多朋友的眼中,AOP似乎是一个很神秘的东西,其实在我看来,AOP的本质就是对一切操作行为的拦截,在.Net中,AOP的本质更简单,纯粹是对方法的拦截。为什么这么说呢?因为在.Net中,一切的操作都是方法调用:事件的 “+=” 及 “-=”最终被转换为 Addxxxx(...),Removexxxxx(...)类型的方法;属性的 get/set 过程也被转换为 getxxxxxx(...),setxxxxxx(...)类型的方法;而方法的本身就更不用说了。


    方法拦载的实现的原理是动态构建类型,动态构建类型的功能是由“mscorlib.dll” 这个.Net核心的程序集提供的,有兴趣的朋友可以详细研究一下这个程序集的“System.Reflection.Emit”命名空间的内容。由于方法的拦载是动态构建类型,所以我们在拦截类方法时,可以采取用动态构造类的方式,从该类继承一个子类,重载并改写类中需要拦截的方法。因此,我们不难理解,为什么在Castle 的 AOP中实现对类方法的拦截,都需要该类中的可被拦载的方法都是能够被子类重载的(override)。

    说了这么多,让我们来写一个简单的程序来演示在 Castle 中AOP 的基础吧,先看看一个简单的类型:


     

    Person的代码
    1. using System;   
    2.   
    3. namespace Unit6   
    4. {   
    5.     public class Person   
    6.     {   
    7.         public virtual void SayHello()   
    8.         {   
    9.             Console.WriteLine("Hello!");   
    10.         }   
    11.   
    12.         public virtual void SayName()   
    13.         {   
    14.             Console.WriteLine("My Name is Roger");   
    15.         }   
    16.   
    17.         public void SayOther()   
    18.         {   
    19.             Console.WriteLine("Yes,I do!");   
    20.         }   
    21.     }   
    22. }  


    这个类型没什么好说的,只是输出一些字符串而以。惟一需要注意的是:前两个方法都是虚方法,而“SayOther”不是虚方法,即是说“SayOther”不可以用一般的方式重载


    再来看看方法拦载器的代码:


     

    拦载器的代码
    1. using System;   
    2. using Castle.DynamicProxy;   
    3.   
    4. namespace Unit6   
    5. {   
    6.     public class SimpleInterceptor : StandardInterceptor   
    7.     {   
    8.         protected override void PreProceed(   
    9.             IInvocation invocation, params object[] args)   
    10.         {   
    11.             Console.WriteLine("Simple Interceptor Running! Method Name:{0}."  
    12.                 , invocation.Method.Name);   
    13.             base.PreProceed(invocation, args);   
    14.         }   
    15.     }   
    16. }  


    Castle DynamicProxy提供了一个标准的方法拦截器,在一般的情况下,从这个标准的拦截器继承便可以完成大部分方法拦载上面的需求。StandardInterceptor中提供了三个可重载的方法:

    1. PreProcced,在进入拦截的方法之前调用。
    2. PostProcced,在拦截的方法运行完成后调用。
    3. Intercept,在拦截的方法返回时调用


    正如上面的代码所展示的,我们会在被拦载的方法调用之前,输出相关的一些信息,接下来我们来看看如何使用这个写好的拦截器


     

    C#代码
    1. using System;   
    2. using Castle.DynamicProxy;   
    3.   
    4. namespace Unit6   
    5. {   
    6.     internal class Program   
    7.     {   
    8.         private static void Main()   
    9.         {   
    10.             SimpleInterceptor interceptor = new SimpleInterceptor();   
    11.             ProxyGenerator generator = new ProxyGenerator();   
    12.             Person person = (Person) generator.   
    13.                 CreateClassProxy(typeof (Person), interceptor);   
    14.   
    15.   
    16.             Console.WriteLine("Current Type:{0},Base Type:{1}",    
    17.                 person.GetType(), person.GetType().BaseType);   
    18.             Console.WriteLine();   
    19.   
    20.                
    21.             person.SayHello();   
    22.             Console.WriteLine();   
    23.   
    24.             person.SayName();   
    25.             Console.WriteLine();   
    26.   
    27.             person.SayOther();   
    28.   
    29.             Console.ReadLine();   
    30.         }   
    31.     }   
    32. }  


    在上面的代码中,ProxyGenerator其实是一个动态的类型构造器,它依据Person类型,并加入相应的拦载器构造出了一个新的类型,我们来查看一下运行输出:


    根据输出的第一行,我们可以知道,ProxyGenerator构造了一个新的类型,这个类型继承自Person,由于这个类型的SayOther方法不可以被子类重载,所以这个方法无法被拦截。

    点击下载程序源文件

  • 相关阅读:
    Java Web Jsp EL ${ user.name }
    Java Web 网络留言板5 (javaBean技术)
    Java Web Web应用,打包和web.xml文件
    Java Web JSTL (实例)
    基于wpf的相关设计问题ViewModel
    c++ primer学习笔记(1)
    记上海俱乐部活动
    c++ primer学习笔记(3)字符串操作
    wpf&& silverlight的Behavior
    基于wpf的相关设计问题Command的使用
  • 原文地址:https://www.cnblogs.com/isuper/p/1239066.html
Copyright © 2020-2023  润新知