博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 用delegate实现AOP事务[C# | AOP | delegate]
阅读量:6038 次
发布时间:2019-06-20

本文共 4732 字,大约阅读时间需要 15 分钟。

我们先来看一段代码雏形:

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

本文转自博客园农民伯伯的博客,原文链接:,如需转载请自行联系原博主。

你可能感兴趣的文章
制作ubuntu系统u盘镜像,以及安装
查看>>
JAVA多线程深度解析
查看>>
Kafka High Level Consumer 会丢失消息
查看>>
时间轴
查看>>
java 获取系统当前时间的方法
查看>>
Ubuntu 10.04升级git 到1.7.2或更高的可行方法
查看>>
Spring Security4实战与原理分析视频课程( 扩展+自定义)
查看>>
消息队列服务器 memcacheq的搭建
查看>>
VMware Horizon View 7.5 虚拟桌面实施咨询与购买--软件硬件解决方案
查看>>
RabbitMQ如何保证队列里的消息99.99%被消费?
查看>>
第一周博客作业
查看>>
thinkpython2
查看>>
String、StringBuffer和StringBuilder的区别
查看>>
oracle recyclebin与flashback drop
查看>>
svmlight使用说明
查看>>
Swing 和AWT之间的关系
查看>>
Mysql设置自增长主键的初始值
查看>>
Android计时器正确应用方式解析
查看>>
获取post传输参数
查看>>
ASP生成静态页面的方法
查看>>