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方式得定义尽可能多的方法形式,这点比较不方便。

 

结束

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


转载:http://www.cnblogs.com/over140/archive/2009/01/09/1372255.html

目录
相关文章
|
7月前
|
XML Java 数据格式
13Spring - Spring转账Demo(了解事务及AOP)
13Spring - Spring转账Demo(了解事务及AOP)
28 0
|
3天前
|
Java 数据库连接 数据库
AOP&事务
AOP&事务
5 0
|
5月前
|
XML Java 数据库连接
【Spring】JDBC、AOP、事务
【Spring】JDBC、AOP、事务
|
5月前
|
Java Spring
使用spring的aop实现全局的事务控制
使用spring的aop实现全局的事务控制
46 0
|
5月前
|
XML Java 编译器
Spring的AOP和事务
Spring的AOP和事务
28 0
|
8月前
|
SQL 存储 数据库
C#三十三 事务
C#三十三 事务
26 0
|
9月前
|
XML Java 数据库连接
2021-08-10基于注解配置AOP,银行取款初步后台搭建,spring事务处理,注解方式事务配置,spring+mybatis整合
2021-08-10基于注解配置AOP,银行取款初步后台搭建,spring事务处理,注解方式事务配置,spring+mybatis整合
340 1
|
10月前
|
存储 SpringCloudAlibaba Java
Spring基于AOP事务控制实现原理
对于一个系统应用而言,使用数据库进行数据存储是必然的,意味着开发过程中事务的使用及控制也是必不可少的,当然事务是数据库层面的知识点并不是`Spring`框架所提出的。使用JDBC开发时,我们使用`connnection`对事务进行控制,使用`MyBatis`时,我们使用`SqlSession`对事务进行控制,缺点显而易见,当我们切换数据库访问技术时,事务控制的方式总会变化,所以`Spring` 就在这些技术基础上,提供了统一的控制事务的接口。Spring的事务分为:编程式事务控制和声明式事务控制
31296 10
Spring基于AOP事务控制实现原理
|
11月前
|
JSON 算法 安全
JavaWeb基础知识-登录效验-spring事务-AOP(二)
2.JWT令牌 全称:JSON Web Token (https:/ljwt.io/) 定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的。 组成: 第一部分:Header(头),记录令牌类型、签名算法等。例如: {“alg”:“HS256” ,“type” :“JWT”} 第二部分: Payload(有效载荷),携带一些自定义信息、默认信息等。例如:{“id”.“1” ,“username”:“Tom”} 第三部分: Signature(签名),防止Token被篡改、确保安全性。将header、 payload,并加入指定秘钥
|
12月前
|
监控 Java Spring
Spring JDBC-实施Spring AOP事务注意事项及案例分析
Spring JDBC-实施Spring AOP事务注意事项及案例分析
110 0