1. 程式人生 > >Castle AOP 系列(一):對類方法呼叫的攔截(有原始碼)

Castle AOP 系列(一):對類方法呼叫的攔截(有原始碼)

Castle的相關網站:

在Castle的2.5以上版本,已經將 Castle.DynamicProxy2.dll 裡有內容,整合到 Castle.Core.dll 中。

所以,朋友們,不需要再去哪裡找Castle.DynamicProxy2.dll了。

當然,除非你使用低於2.5的版本。

本文使用的Castle.Core.dll是3.1版本。

由於方法的攔載是動態構建型別,所以我們在攔截類方法時,可以採取用動態構造類的方式,從該類繼承一個子類,過載並改寫類中需要攔截的方法。

因此,我們不難理解,為什麼在Castle 的 AOP中實現對類方法的攔截,都需要該類中的可被攔載的方法都是能夠被子類過載的(override)。

CastleAOPTest.Lib.Person的程式碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CastleAOPTest.Lib
{
    public class Person
    {
        public virtual void SayHello()
        {
            Console.WriteLine("您好!");
        }

        public virtual void SayName(string pHometown)
        {
            Console.WriteLine("我是天涯人,我來自:{0}。", pHometown);
        }

        public void SayOther()
        {
            Console.WriteLine("是的,我是中國人。");
        }

    }
}

這個型別沒什麼好說的,只是輸出一些字串而以。

惟一需要注意的是:前兩個方法都是虛方法,而“SayOther”不是虛方法,即是說“SayOther”不可以用一般的方式過載。

方法攔載器CastleAOPTest.Lib.AOP.SimpleInterceptor的程式碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using CastleAOPTest.Lib;
using Castle.DynamicProxy;

namespace CastleAOPTest.Lib.AOP
{
    public class SimpleInterceptor : StandardInterceptor
    {
        protected override void PreProceed(IInvocation invocation)
        {
            Console.WriteLine("呼叫前的攔截器,方法名是:{0}。", invocation.Method.Name);
            base.PreProceed(invocation);

        }

        protected override void PerformProceed(IInvocation invocation)
        {
            Console.WriteLine("攔截的方法返回時呼叫的攔截器,方法名是:{0}。", invocation.Method.Name);
            base.PerformProceed(invocation);

        }


        protected override void PostProceed(IInvocation invocation)
        {
            Console.WriteLine("呼叫後的攔截器,方法名是:{0}。", invocation.Method.Name);
            base.PostProceed(invocation);

        }
    }
}

Castle DynamicProxy提供了一個標準的方法攔截器,在一般的情況下,從這個標準的攔截器繼承便可以完成大部分方法攔載上面的需求。

StandardInterceptor中提供了三個可過載的方法:


1.PreProcced,在進入攔截的方法之前呼叫。

2.PerformProceed,在攔截的方法返回時呼叫。

3.PostProcced,在攔截的方法執行完成後呼叫。

如何使用這個寫好的攔截器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Castle.DynamicProxy;
using CastleAOPTest.Lib;
using CastleAOPTest.Lib.AOP; 

namespace CastleAOPTest.Run
{
    class Program
    {
        static void Main(string[] args)
        {
            ProxyGenerator generator = new ProxyGenerator();//例項化【代理類生成器】
            SimpleInterceptor interceptor = new SimpleInterceptor();//例項化【攔截器】

            //使用【代理類生成器】建立Person物件,而不是使用new關鍵字來例項化
            Person person = generator.CreateClassProxy<Person>(interceptor);


            Console.WriteLine("當前型別:{0},父型別:{1}",person.GetType(), person.GetType().BaseType);
            Console.WriteLine();


            person.SayHello();//跟普通呼叫沒有兩樣吧?
            Console.WriteLine();

            person.SayName("福建");//跟普通呼叫沒有兩樣吧?
            Console.WriteLine();

            person.SayOther();//它不是虛方法,無法攔截。待會檢測輸出情況就知道了。   



           Console.ReadLine();   

        }
    }
}

ProxyGenerator其實是一個動態的型別構造器,它依據Person型別,並加入相應的攔載器構造出了一個新的型別,我們來檢視一下執行輸出:

根據輸出的第一行,我們可以知道,ProxyGenerator構造了一個新的型別,這個型別繼承自Person。

由於這個型別的SayOther方法不可以被子類過載,所以這個方法無法被攔截。