程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#用delegate實現AOP事務[C# | AOP | delegate]

C#用delegate實現AOP事務[C# | AOP | delegate]

編輯:關於C#

前言

上一篇 C# 用Attribute實現AOP事務 [C# | AOP | Attribute | ContextAttribute | IContributeObjectSink | IMessageSink ]是實現或者說達到AOP效果的一種方式,其實最早設計在C#中使用AOP來完成事務的方案是准備用delegate的,但無奈不習慣用 這個玩意,也理解不深,後來被Attribute吸引了,這個方案就擱淺了,不過現在我又回來了 : ) 

正文

我們先來看一段代碼雛 形:

class TestClass
{
public void Test()
{
Console.WriteLine ("Test");
}
public void DelegateTest(DelegateMethod dm)
{
Console.WriteLine("DelegateMethod Start");
dm.Invoke();
Console.WriteLine ("DelegateMethod End");
}
}
class Program
{
static void Main(string[] args)
{
TestClass tc = new TestClass();
tc.Test();
Console.WriteLine ("-------------------------------");
tc.DelegateTest(new DelegateMethod(mc.Test));
Console.Read();
}
}

輸出結果

Test
-------------------------------
DelegateMethod Start...
Test
DelegateMethod End...

我認為這也是一種AOP的方式,只是和傳統的不太一樣, 如果把調用方和被調用方看成客戶端和服務器的話,那麼傳統的AOP是施加在服務器端的,並在服務器端控制的,而現在我把這個權利交出來, 交給客戶端來控制,也就是由調用者來決定是不是要使用事務,也就是調用者自己決定用事務或非事務的方式來執行方法。請注意:如果到這 裡你不能接受我的想法請不必往下看了 : )

接下來我會把代碼貼全,注意代碼我都測試通過了的: )

SqlDAL.cs 把上篇文章拿 過來拷貝過來改把改把貼上來

       #region 
//事務
private SqlTransaction _SqlTrans;
//數據庫連接類
private SqlConnectionStringBuilder _ConnectionString = null;
#endregion
#region delegate
/// <summary>
/// 用於執行帶Dictionary參數無返回值的函數
/// </summary>
/// <param name="dict"></param>
public delegate void VOID_DICTIONARY_METHOD(Dictionary<string, object> dict);
#endregion
#region Method
#region ExecuteNonQuery
public int ExecuteNonQuery(string cmdText)
{
if (SqlTrans == null)
return SqlHelper.ExecuteNonQuery(ConnectionString.ConnectionString, CommandType.Text, cmdText);
else
return SqlHelper.ExecuteNonQuery(SqlTrans, CommandType.Text, cmdText);
}
public int ExecuteNonQuery(string cmdText, CommandType type)
{
if (SqlTrans == null)
return SqlHelper.ExecuteNonQuery(ConnectionString.ConnectionString, type, cmdText);
else
return SqlHelper.ExecuteNonQuery(SqlTrans, type, cmdText);
}
public int ExecuteNonQuery(string cmdText, CommandType type, params SqlParameter[] cmdParameters)
{
if (SqlTrans == null)
return SqlHelper.ExecuteNonQuery(ConnectionString.ConnectionString, type, cmdText, cmdParameters);
else
return SqlHelper.ExecuteNonQuery(SqlTrans, type, cmdText, cmdParameters);
}
#endregion
/// <summary>
/// 在事務中執行
/// </summary>
/// <param name="action"></param>
/// <param name="args"></param>
public void TransactionAction(Delegate delegateMethod, params object[] args)
{
SqlConnection SqlConnect = new SqlConnection(ConnectionString.ConnectionString);
SqlConnect.Open();
_SqlTrans = SqlConnect.BeginTransaction();
try
{
//數據庫操作
delegateMethod.DynamicInvoke(args);
//提交事務
_SqlTrans.Commit();
}
catch (SqlException)
{
_SqlTrans.Rollback();
//日志
}
finally
{
if (SqlTrans != null)
{
_SqlTrans.Dispose();
_SqlTrans = null;
}
if (SqlConnect != null)
SqlConnect.Close();
}
}
#endregion
#region Properties
/// <summary>
/// 僅支持有事務時操作
/// </summary>
public SqlTransaction SqlTrans
{
get { return _SqlTrans; }
set { _SqlTrans = value; }
}
/// <summary>
/// 字符串連接
/// </summary>
public virtual SqlConnectionStringBuilder ConnectionString
{
get
{
if (_ConnectionString == null || string.IsNullOrEmpty(_ConnectionString.ConnectionString))
{
_ConnectionString = new SqlConnectionStringBuilder(Configurations.SQLSERVER_CONNECTION_STRING);
}
return _ConnectionString;
}
set { _ConnectionString = value; }
}
#endregion

代碼說明:

1.講Delegate作為參數,我們可以傳任何一個delegate進來,不必使用實際的如 VOID_DICTIONARY_METHOD作為參數傳遞,這對於通用是一個很好的辦法。

2.TransactionAction方法第二個參數是你要傳遞的參數,即 委托的參數。MSDN:作為參數傳遞給當前委托所表示的方法的對象數組。- 或 - 如果當前委托所表示的方法不需要參數,則為null。

UserInfoAction.cs 不變

public class UserInfoAction:SqlDAL
{
public void Add (Dictionary<string, object> dict)
{
StringBuilder sql = new StringBuilder();
sql.Append("INSERT [UserInfo](");
ExecuteNonQuery(sql);
}
}

Main

static void Main(string[] args)
{
Dictionary<string, object> dict = new Dictionary<string, object>();
UserInfoAction uiAction = new UserInfoAction();
dict.Add ("Username", "abc");
dict.Add("Password", "abc");
dict.Add("Email", "[email protected]");
//普通方式執行
//uiAction.Add (dict);
//事務方式執行
uiAction.TransactionAction(new UserInfoAction.VOID_DICTIONARY_METHOD (uiAction.Add), dict);
}

代碼說明

1.可以看到普通方式和事務方式執行方式不同,但是我們不用改UserInfoAction的代碼!!我們在寫代碼尤其是維護的時 候就是這樣的原則,或者是增量式開發也是比較好的,盡量不去改是比較好的。

2.請注意:你的delegate必須符合Method,否則編譯時 會出錯的,雖然解決了統一調用的問題,但是這個delegate目前我還沒想到辦法解決,也就是你有一個不同參數、返回值方法就得對應一個 delegate,方法名稱不限制,所以一開始我們就得定義可能好幾十個委托,這也是利弊所在不,不然還是很完美的。

3.有朋友可能覺得 這個決定權不應該交給客戶端來決定,必須事務,那這也好辦,請看代碼:

public class UserInfoAction:SqlDAL
{
public void Add(Dictionary<string, object> dict)
{
TransactionAction(new VOID_DICTIONARY_METHOD(_Add), dict);
}
private void _Add(Dictionary<string, object> dict)
{
UserInfo uInfo = new UserInfo();
uInfo.SetPropertyValue(dict);
Insert (uInfo);
}
}

而我們客戶端代碼又可以切換成普通方式調用了,但實際上他已經處在事務當中了。

比較 與特點

相比Attribute實現AOP事務,有以下幾個特點:

1.delegate方式效率肯定要比Attribute方式高,看看他實例化多少個類 加上多少次反射就知道了。

2.delegate方式我們可以對錯誤進行Catch處理.

3.delegate方式得定義盡可能多的方法形式,這點 比較不方便。

結束

一天半的時間又沒了,但是又多了一種解決方案,我相信沒有最好的解決方案,只有更好的解決方案,所以 我希望當有人問你一個問題的時候,尤其是學習,你盡可能的給出多個方案並幫助他分析各個方案的利弊。歡迎大家提建議 : )

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved