代碼說明:
1.在上面兩篇文章中都是把IContextProperty, IContributeObjectSink單獨繼承並實現的,其實我們發現ContextAttribute已經繼承了IContextProperty,所有這裡我僅僅只需要再繼承一下IContributeObjectSink就行了。關於這兩個接口的說明,上面文章中都有詳細的說明。
2.TransactionAop將在後面給出。
3.需要注意的是兩個Attribute需要一起用,並且我發現Attribute如果標記在類上他會被顯示的實例化,但是放在方法上就不會,打斷點可以跟蹤到這一過程,要不然我也不會費力氣弄兩個來標注了。
TransactionAop.cs
public sealed class TransactionAop : IMessageSink
{
private IMessageSink nextSink; //保存下一個接收器
/// <summary>
/// 構造函數
/// </summary>
/// <param name="next">接收器</param>
public TransactionAop(IMessageSink nextSink)
{
this.nextSink = nextSink;
}
/// <summary>
/// IMessageSink接口方法,用於異步處理,我們不實現異步處理,所以簡單返回null,
/// 不管是同步還是異步,這個方法都需要定義
/// </summary>
/// <param name="msg"></param>
/// <param name="replySink"></param>
/// <returns></returns>
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
{
return null;
}
/// <summary>
/// 下一個接收器
/// </summary>
public IMessageSink NextSink
{
get { return nextSink; }
}
/// <summary>
///
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public IMessage SyncProcessMessage(IMessage msg)
{
IMessage retMsg = null;
IMethodCallMessage call = msg as IMethodCallMessage;
if (call == null || (Attribute.GetCustomAttribute(call.MethoDBase, typeof(TransactionMethodAttribute))) == null)
retMsg = nextSink.SyncProcessMessage(msg);
else
{
//此處換成自己的數據庫連接
using (SqlConnection Connect = new SqlConnection(Configurations.SQLSERVER_CONNECTION_STRING))
{
Connect.Open();
SqlTransaction SqlTrans = Connect.BeginTransaction();
//講存儲存儲在上下文
CallContext.SetData(TransactionAop.ContextName, SqlTrans);
//傳遞消息給下一個接收器 - > 就是指執行你自己的方法
retMsg = nextSink.SyncProcessMessage(msg);
if (SqlTrans != null)
{
IMethodReturnMessage methodReturn = retMsg as IMethodReturnMessage;
Exception except = methodReturn.Exception;
if (except != null)
{
SqlTrans.Rollback();
//可以做日志及其他處理
}
else
{
SqlTrans.Commit();
}
SqlTrans.Dispose();
SqlTrans = null;
}
}
}
return retMsg;
}
/// <summary>
/// 用於提取、存儲SqlTransaction
/// </summary>
public static string ContextName
{
get { return "TransactionAop"; }
}
}