巧用“Delegate”实现AOP事务
2014-11-30 11:28
246 查看
为了保持应用程序的完整性,事务处理,是项目开发中的必不可缺的部分,且重要性不言而喻。传统的处理方式是手动控制事务的开闭,这样,不管谁用到事务处理都得自己写一遍代码。为了方便,达到AOP效果不失为一个好办法。我们用Delegate来实现一下这个效果。
输出结果:
我觉得这就是AOP的方式,只是和传统的不太一样,如果把调用方和被调用方看成客户端和服务器的话,那么传统的AOP是施加在服务器端的,并在服务器端控制的,而现在我把这个权利交出来,交给客户端来控制,也就是由调用者来决定是不是要使用事务,也就是调用者自己决定用事务或非事务的方式来执行方法。
把Delegate作为参数,我们可以传任何一个delegate进来,不必使用实际的如VOID_DICTIONARY_METHOD作为参数传递,这对于通用是一个很好的办法。
ransactionAction方法第二个参数是你要传递的参数,即委托的参数。MSDN:作为参数传递给当前委托所表示的方法的对象数组。- 或 - 如果当前委托所表示的方法不需要参数,则为null。
2. 请注意:delegate必须符合Method,否则编译时会出错的,虽然解决了统一调用的问题,但是这个delegate目前我还没想到办法解决,也就是你有一个不同参数、返回值方法就得对应一个delegate,方法名称不限制,所以一开始我们就得定义可能好几十个委托,这也是利弊所在不,不然还是很完美的。
一、为了展示效果,我们先来看一个小demo:
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(); } }
输出结果:
我觉得这就是AOP的方式,只是和传统的不太一样,如果把调用方和被调用方看成客户端和服务器的话,那么传统的AOP是施加在服务器端的,并在服务器端控制的,而现在我把这个权利交出来,交给客户端来控制,也就是由调用者来决定是不是要使用事务,也就是调用者自己决定用事务或非事务的方式来执行方法。
二、接下来看看具体的代码
1. 先看看SqlDAL.cs的代码:
public class SqlDAL { #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 }代码说明:
把Delegate作为参数,我们可以传任何一个delegate进来,不必使用实际的如VOID_DICTIONARY_METHOD作为参数传递,这对于通用是一个很好的办法。
ransactionAction方法第二个参数是你要传递的参数,即委托的参数。MSDN:作为参数传递给当前委托所表示的方法的对象数组。- 或 - 如果当前委托所表示的方法不需要参数,则为null。
2.接下来看看 UserInfoAction.cs 和 Main 的代码:
public class UserInfoAction : SqlDAL { public void Add(Dictionary<string, object> dict) { StringBuilder sql = new StringBuilder(); sql.Append("INSERT [UserInfo]("); …… ExecuteNonQuery(sql); } }
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", "over140@gmail.com"); //普通方式执行 //uiAction.Add(dict); //事务方式执行 uiAction.TransactionAction(new UserInfoAction.VOID_DICTIONARY_METHOD(uiAction.Add), dict); }
三、总结
1. 可以看到普通方式和事务方式执行方式不同,但是我们不用改UserInfoAction的代码!!我们在写代码尤其是维护的时候就是这样的原则,或者是增量式开发也是比较好的,尽量不去改是比较好的。现在完全满足“开闭原则”。2. 请注意:delegate必须符合Method,否则编译时会出错的,虽然解决了统一调用的问题,但是这个delegate目前我还没想到办法解决,也就是你有一个不同参数、返回值方法就得对应一个delegate,方法名称不限制,所以一开始我们就得定义可能好几十个委托,这也是利弊所在不,不然还是很完美的。
相关文章推荐
- C# 用delegate实现AOP事务[C# | AOP | delegate]
- C# 用delegate实现AOP事务[C# | AOP | delegate]
- C# 用delegate实现AOP事务[C# | AOP | delegate]
- 85-002-3 spring与hibernate的整合(采用AOP来管理事务实现声明式事务)
- Spring Mvc那点事---(33)Spring事务基于AOP实现
- Atomikos+spring AOP方式实现JTA事务配置的示例
- 从零实现MVC框架之AOP事务(5)
- bboss-persistent结合bboss-aop实现注解事务
- springAOP 实现事务的管理
- spring源码分析之——spring 事务管理实现方式 (不太清晰,不明白aop会看不懂)
- Asp.Net大型项目实践(7)-用Unity实现AOP之事务处理+为啥要用AOP(附源码)
- [AOP系列]Autofac+Castle实现AOP事务
- Spring aop实现事务加锁
- 基于spring的aop实现读写分离与事务配置
- 学习笔记:spring与hibernate整合(采用aop来管理事务来实现声明式事务)
- C#.NET利用ContextBoundObject和Attribute实现AOP技术--AOP事务实现例子
- 用Attribute实现AOP事务
- 【Java基础】动态代理实现AOP之控制事务
- C# 用Attribute实现AOP事务 [C# | AOP | Attribute | ContextAttribute | IContributeObjectSink | IMessageSink