C# 用delegate实现AOP事务[C# | AOP | delegate]

前言

     上一篇 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 " " over140@gmail.com " );
            
// 普通方式执行
            
// 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方式得定义尽可能多的方法形式,这点比较不方便。

 

结束

     一天半的时间又没了,但是又多了一种解决方案,我相信没有最好的解决方案,只有更好的解决方案,所以我希望当有人问你一个问题的时候,尤其是学习,你尽可能的给出多个方案并帮助他分析各个方案的利弊。欢迎大家提建议 : )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值