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(); } } }