C#使用Castle實現AOP面向切面編程


Castle.Core 本質是創建繼承原來類的代理類,重寫虛方法實現AOP功能。個人覺得比Autofac用着爽

使用方式比較簡單,先新建一個控制台項目,然后在Nuget上搜索Castle.Core並安裝,如下順序:

或者通過命令安裝:

Install-Package Castle.Core -Version 3.3.3

安裝成功之后,如下圖:

1. 創建攔截器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//先在Nuget上搜索Castle安裝
using Castle.DynamicProxy;

namespace CastleDEMO
{
    /// <summary>
    /// 攔截器 需要實現 IInterceptor接口 Intercept方法
    /// </summary>
    public class DA_LogInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            try
            {
                DateTime begin = DateTime.Now;

                Console.WriteLine("開始DAL {0}調用!", invocation.Method.Name);

                //在被攔截的方法執行完畢后 繼續執行
                invocation.Proceed();
                
                DateTime end = DateTime.Now;
                Console.WriteLine("結束DAL {0}調用!耗時:{1}ms", invocation.Method.Name, (end - begin).TotalMilliseconds);
            }
            catch (Exception ex)
            {
                string methodName = "DA_" + invocation.TargetType.ToString() + "." + invocation.Method.Name;
                Console.WriteLine("{0}方法錯誤:{1}", methodName, ex.Message);
                //如果沒有定義異常處理返回值,就直接拋異常
                if (!invocation.Method.IsDefined(typeof(ExceptionReturnAttribute), false))
                    throw;
                var ls = invocation.Method.GetCustomAttributes(typeof(ExceptionReturnAttribute), false);
                if (null == ls || ls.Length <= 0)
                    throw;

                ExceptionReturnAttribute v = (ExceptionReturnAttribute)ls[0];
                if (null == v.Value && null == v.Type)
                {
                    invocation.ReturnValue = null;
                    return;
                }
                if (null != v.Value)
                {
                    invocation.ReturnValue = v.Value;
                    return;
                }
                if (null != v.Type)
                {
                    invocation.ReturnValue = Activator.CreateInstance(v.Type);
                    return;
                }
            }
        }

        /// <summary>
        /// <para>DAO層異常時,不throw,返回設定的值.</para>
        /// <para>1. 返回復雜類型,使用Type,復雜類型需要有無參的構造函數</para>
        /// <para>2. 返回簡單類型,使用value</para>
        /// </summary>
        [AttributeUsage(AttributeTargets.Method)]
        public class ExceptionReturnAttribute : System.Attribute
        {
            /// <summary>
            /// 返回復雜類型,使用Type,復雜類型需要有無參的構造函數
            /// </summary>
            public Type Type { get; set; }

            /// <summary>
            /// 返回簡單類型,使用value
            /// </summary>
            public object Value { get; set; }
        }
    }
}

2. 創建攔截容器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Castle.DynamicProxy;

namespace CastleDEMO
{
    /// <summary>
    /// Dao 類的接口
    /// 繼承實現BaseDao的類,其相關接口訪問的公共方法必須要聲明 virtual 方法才能被攔截器攔截。
    /// </summary>
    public abstract class BaseDao
    {
       
    }

    /// <summary>
    /// Dao容器,必須依賴於此類來創建Dao對象,使Dao受控,可進行檢查等
    /// </summary>
    public class DaoContainer
    {
        //ProxyGenerator上自身有緩存
        //實例化【代理類生成器】 
        public static ProxyGenerator generator = new ProxyGenerator();
        public static T GetDao<T>() where T : BaseDao
        {
            //實例化【攔截器】 
            DA_LogInterceptor interceptor = new DA_LogInterceptor();
            //使用【代理類生成器】創建T對象,而不是使用new關鍵字來實例化 
            return generator.CreateClassProxy<T>(interceptor);
        }
    }
}

3. 新建實例類

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

namespace CastleDEMO
{
    public abstract class PersonDAL : BaseDao
    {
        /// <summary>
        /// 必須是虛方法才能被攔截器攔截
        /// </summary>
        public virtual void SayHello()
        {
            Console.WriteLine("我是虛方法{0}方法", "SayHello");
        }
        public virtual void SayName(string name)
        {
            Console.WriteLine("我是虛方法{0}方法,參數值:{1}", "SayName", name);
        }
        public abstract void AbstactSayOther();
        public void SayOther()
        {
            Console.WriteLine("我是普通方法{0}方法", "SayOther");
        }
    }
}

4. 測試

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

namespace CastleDEMO
{
    public class Program
    {
        public static void Main(string[] args)
        {
            PersonDAL person = DaoContainer.GetDao<PersonDAL>();
            Console.WriteLine("當前類型:{0},父類型:{1}", person.GetType(), person.GetType().BaseType);
            Console.WriteLine();
            person.SayHello();//攔截
            Console.WriteLine();
            person.SayName("Never、C");//攔截
            Console.WriteLine();
            person.SayOther();//普通方法,無法攔截    
            //person.AbstactSayOther();//抽象方法,可以攔截(但是如果方法沒實現攔截時會報錯)     
            Console.ReadLine();
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM