PostSharp是基於.NET平台設計的比較強調易學易用的AOP架構,AOP的概念,優點請參見:
http://www.cnblogs.com/wayfarer/category/35983.html
這裡只是簡要的介紹幾種使用PostSharp實現的情境供大家參考。
一、日誌
一般我們寫入業務方面的日誌有兩種方式,
1、簡單的記錄業務方法的發生時間,觸發使用者,業務方法名等
傳統方案我們是這樣記錄的。
public class Employee
{
public void Add(string employeeName, string employeePwd)
{
Console.WriteLine("添加員工名:{0},密碼:{1}",employeeName,employeePwd);
LogManager.LogWrite("Add");
}
}
class LogManager
{
public static void LogWrite(string methodName)
{
GenericPrincipal gp = (GenericPrincipal)Thread.GetData(
Thread.GetNamedDataSlot("Principal"));
Console.WriteLine("使用者名稱:{0},日誌時間:{1},觸發此日誌的方法:{2}",
gp.Identity.Name, DateTime.Now.ToString(), methodName);
}
}
//主程式:
static void Main(string[] args)
{
GenericIdentity gi = new GenericIdentity("lfm");
GenericPrincipal gp = new GenericPrincipal(gi, new string[] { "Admin" });
LocalDataStoreSlot localSlot = Thread.AllocateNamedDataSlot("Principal");
Thread.SetData(localSlot, gp);
Employee em = new Employee();
em.Add("lfm","lfm");
}
(因為這裡使用的控制台應用程式,為了便於測試我們使用了線程槽來儲存使用者,如果不理解這個部分可以暫時忽略使用者資訊。)傳統方案的日誌記錄的問題是每個需要記錄日誌的方法都要依賴於LogManager類,也就是說所有的商務邏輯都要依賴於系統級的LogManager類,我們能不能讓他們徹底的分離開呢,下面我們使用PostSharp提供的方式來解決這個問題。
要使用PostSharp必須先下載(http://www.postsharp.org/)PostSharp,安裝之後需要至少引入PostSharp.Laos,PostSharp.Public兩個程式集。PostSharp是利用特性(Attribute)將業務類和系統類別聯絡在一起的,所以我們需要首先定義SampleLogAttribute類如下:
使用postSharp記錄日誌
[Serializable]
class SampleLogAttribute : OnMethodBoundaryAspect
{
public override void OnSuccess(MethodExecutionEventArgs eventArgs)
{
LogManager.LogWrite(eventArgs);
}
}
日誌記錄類:
class LogManager
{
public static void LogWrite(MethodExecutionEventArgs eventArgs)
{
GenericPrincipal gp = (GenericPrincipal)Thread.GetData(
Thread.GetNamedDataSlot("Principal"));
Console.WriteLine("使用者名稱:{0},日誌時間:{1},觸發此日誌的方法:{2}",
gp.Identity.Name, DateTime.Now.ToString(),
eventArgs.Instance.ToString() + "." + eventArgs.Method.Name);
}
}
然後在需要記錄日誌的方法上標識SampleLogAttribute即可
相應方法
[SampleLog]
public void Add(string employeeID, string pwd)
{
Console.WriteLine("使用者名稱:{0}密碼:{1}", employeeID, pwd);
}
這時我們運行程式會得到如下結果:
這裡我們需要去瞭解一下OnMethodBoundaryAspect類,我們可以通過重寫OnEntry,OnSuccess兩個方法來截獲方法的資訊,OnEntry是在標識了相應特性的方法前觸發,而OnSuccess是在標識了相應特性的方法後觸發。
2、我們可能需要記錄方法的一些更詳細的資訊,比如說更新操作,我們需要記錄更新前的資訊
日誌的記錄特性代碼如下:
複雜日誌記錄
[Serializable]
class UpdateLogAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
LogManager.LogWrite(eventArgs);
foreach (var item in eventArgs.Instance.GetType().GetProperties())
{
Console.WriteLine("原屬性名稱:{0},原值:{1}",item.Name,
item.GetValue(eventArgs.Instance,null));
}
Console.WriteLine();
}
}
//業務類:
class Employee
{
public Employee(string employeeID, string pwd)
{
this.EmployeeID = employeeID;
this.Pwd = pwd;
}
[UpdateLog]
public void Update(Employee em)
{
this.EmployeeID = em.EmployeeID;
this.Pwd = em.Pwd;
Console.WriteLine("更新後:employeeID:{0},pwd:{1}",this.EmployeeID,this.Pwd);
}
public string EmployeeID { get; set; }
public string Pwd { get; set; }
}
運行主程式結果如下:
也許還有些情況日誌記錄會更複雜,但一般情況下我們都可以通過截獲方法的參數,執行個體的屬性等獲得想要的資訊。可能你會覺得這樣一個一個寫特性也挺麻煩,PostSharp提供了一種廣播橫切點的方式,我們可以在類上使用相關的特性然後設定其AttributeTargetMembers值,如:
[SampleLog(AttributeTargetMembers = "Add*")]
class Employee
{
}
這樣Employee類中所有使用Add開頭的方法都將記錄日誌,也可以設定整個程式集,大家可以參考PostSharp提供的文檔。
源碼下載