一起谈.NET技术,利用AOP重构代码

简介:   AOP是什么?    AOP是OOP的延续,Aspect Oriented Programming的缩写,即面向方面编程。AOP是GoF设计模式的延续,设计模式追求的是调用者和被调用者之间的解耦,AOP也是这种目标的一 种实现。

  AOP是什么?  
  AOP是OOP的延续,Aspect Oriented Programming的缩写,即面向方面编程。AOP是GoF设计模式的延续,设计模式追求的是调用者和被调用者之间的解耦,AOP也是这种目标的一 种实现。  
  案例:在应用程序中,我们经常会对某一段程序做异常处理,或者是把一个方法的调用所消耗的时间体现在日志中,如果我们对每个方法都写具体的实现,我想并不是一件轻松的事情。对于异常处理来讲,其实我们平常编程很少去捕获具体的异常,当然特殊程序除外,例如客户端捕获WCF异常时最好捕获CommunicationException,TimeoutException,Exception。否则一般都会直接捕获Exception,因为很多异常往往是意料之外的异常。对于记录方法调用时间问题,我想也非常麻烦,下面例子简单的展示了记录时间:当你需要对多个方法都需要记录时间时,这些代码往往让人感觉有重构的必要。

 

Stopwatch sw  =   new  Stopwatch();
   sw.Start();
   
// 方法执行.....
   sw.Stop();
   WebLog.SquareLog.CommonLogger.Error(
" 取积分广场首页酒店数据用时: " + sw.ElapsedMilliseconds .ToString () + " 毫秒 " );

 

      上面的记录方法调用用时,如果抽象出来,其实有下列特性:
      1:不是具体访问类的首要或主要功能,访问类主要功能是业务逻辑处理。
      2:具体访问类的主要功能可以独立、区分开来的。
      3:是这个系统的一个纵向切面,涉及多个类、多个类的方法。示意图如下:
 
     

 

      aspect:  新的程序结构关注系统的纵向切面,例如这里的异常处理以及方法调用时间记录,这个新的程序结构就是aspect(方面),方面(aspect)应该有以下职责:提供一些必备的功能,对被访问对象实现特有功能,以保证所以方法在被执行时都能正常的执行异常处理或者是其它的功能。


      AOP应用范围
      1:Authentication 权限
      2:Error handling 错误处理
      3:logging, tracing, profiling and monitoring 记录跟踪 优化 校准
      ......

     AOP具体实现:主要是利用泛型委托来实现AOP思想。但泛型委托有一个局限就是最多支持四个参数,当你的方法超过四个时就不太好应用AOP重构了。我最近分析了有以下三个地方我们可以对代码进行优化:


  第一:普通方法异常处理:ErrorHandler类,实现类参考第二或者是第三。

    客户端调用:

代码
string  ErrorMethodText = " 取积分广场首页酒店数据异常: " ;
           list 
=  ErrorWCFHandler .Invoke < ISearchHotelForSquare, List < HotelGenericInfo >> (cli, proxy  =>  proxy.GetHotelGenericListForSquare(requestInfo).ToList() ); 

 
  第二:客户端调用WCF的异常处理:ErrorWCFHandler。

    代码:

代码
public    class  ErrorWCFHandler
    {
       
public   static   void  Invoke < TContract > (TContract proxy, Action < TContract >  action,  string  MethodElapsedTimeText,  string  MethodErrorText)
        {
            Stopwatch sw 
=   new  Stopwatch();
            sw.Start();
            
try
            {
                action(proxy);
                (proxy 
as  ICommunicationObject).Close();
            }
            
catch  (CommunicationException ex)
            {
                (proxy 
as  ICommunicationObject).Abort();
                
// Handle Exception             
                
// throw;
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());
            }
            
catch  (TimeoutException ex)
            {
                (proxy 
as  ICommunicationObject).Abort();
                
// Handle Exception         
                
// throw;
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());
            }
            
catch  (Exception ex)
            {
                
// Handle Exception        
                
// (proxy as ICommunicationObject).Close();      
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());
            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText 
+  sw.ElapsedMilliseconds.ToString()  +   " 毫秒 " );
        }
       
public   static  TReturn Invoke < TContract, TReturn > (TContract proxy, Func < TContract, TReturn >  func,  string  MethodElapsedTimeText,  string  MethodErrorText)
        {
            Stopwatch sw 
=   new  Stopwatch();
            sw.Start();
            TReturn returnValue 
=   default (TReturn);
            
try
            {
                returnValue 
=  func(proxy);
            }
            
catch  (CommunicationException ex)
            {
                (proxy 
as  ICommunicationObject).Abort();
                
// Handle Exception     
                
// throw;
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());
            }
            
catch  (TimeoutException ex)
            {
                (proxy 
as  ICommunicationObject).Abort();
                
// Handle Exception       
                
// throw;
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());
            }
            
catch  (Exception ex)
            {
                
// Handle Exception  
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());
            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText 
+  sw.ElapsedMilliseconds.ToString()  +   " 毫秒 " );
            
return  returnValue;
        }
    }

    客户端调用:         

代码
string  ComputationTimeText = " 取积分广场首页酒店数据耗时: " ;
           
string  ErrorMethodText = " 取积分广场首页酒店数据异常: " ;
           list 
=  ErrorWCFHandler .Invoke < ISearchHotelForSquare, List < HotelGenericInfo >> (cli, proxy  =>  proxy.GetHotelGenericListForSquare(requestInfo).ToList

(),ComputationTimeText ,ErrorMethodText );  

  第三:记录方法调用时间,这中间也增加了异常处理:ErrorAndComputationTimeHandler

    代码:

代码
  public   class  ErrorAndComputationTimeHandler
    {
        
public   static   void  Invoke < TContract > (TContract proxy, Action < TContract >  action,  string  MethodElapsedTimeText, string  MethodErrorText)
        {
            Stopwatch sw 
=   new  Stopwatch();
            sw.Start();
            
try
            {
                action(proxy);

            }
            
catch  (Exception ex)
            {
                
// Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  
+  sw.ElapsedMilliseconds.ToString()  +   " 毫秒 " );
        }
        
public   static   void  Invoke < TContract, TContract2 > (TContract proxy, TContract2 proxy2, Action < TContract, TContract2 >  action,  string  MethodElapsedTimeText, string  MethodErrorText)
        {
            Stopwatch sw 
=   new  Stopwatch();
            sw.Start();
            
try
            {
                action(proxy, proxy2);

            }
            
catch  (Exception ex)
            {
                
// Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  
+  sw.ElapsedMilliseconds.ToString()  +   " 毫秒 " );
        }
        
public   static   void  Invoke < TContract, TContract2, TContract3 > (TContract proxy, TContract2 proxy2, TContract3 proxy3, Action < TContract, TContract2, TContract3 >  action,  string  MethodElapsedTimeText, string  MethodErrorText)
        {
            Stopwatch sw 
=   new  Stopwatch();
            sw.Start();
            
try
            {
                action(proxy, proxy2, proxy3);

            }
            
catch  (Exception ex)
            {
                
// Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  
+  sw.ElapsedMilliseconds.ToString()  +   " 毫秒 " );
        }
        
public   static   void  Invoke < TContract, TContract2, TContract3, TContract4 > (TContract proxy, TContract2 proxy2, TContract3 proxy3, TContract4 proxy4, Action < TContract, TContract2, TContract3, TContract4 >  action,   string  MethodElapsedTimeText, string  MethodErrorText)
        {
            Stopwatch sw 
=   new  Stopwatch();
            sw.Start();
            
try
            {
                action(proxy, proxy2, proxy3, proxy4);

            }
            
catch  (Exception ex)
            {
                
// Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  
+  sw.ElapsedMilliseconds.ToString()  +   " 毫秒 " );
        }
        
public   static  TReturn Invoke < TContract, TReturn > (TContract proxy, Func < TContract, TReturn >  func,   string  MethodElapsedTimeText, string  MethodErrorText)
        {
            Stopwatch sw 
=   new  Stopwatch();
            sw.Start();
            TReturn returnValue 
=   default (TReturn);
            
try
            {
                returnValue 
=  func(proxy);
            }
            
catch  (Exception ex)
            {
                
// Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  
+  sw.ElapsedMilliseconds.ToString()  +   " 毫秒 " );
            
return  returnValue;
        }
        
public   static  TReturn Invoke < TContract, TContract2, TReturn > (TContract proxy, TContract2 proxy2, Func < TContract, TContract2, TReturn >  func,   string  MethodElapsedTimeText, string  MethodErrorText)
        {
            Stopwatch sw 
=   new  Stopwatch();
            sw.Start();
            TReturn returnValue 
=   default (TReturn);
            
try
            {
                returnValue 
=  func(proxy, proxy2);
            }
            
catch  (Exception ex)
            {
                
// Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  
+  sw.ElapsedMilliseconds.ToString()  +   " 毫秒 " );
            
return  returnValue;
        }
        
public   static  TReturn Invoke < TContract, TContract2, TContract3, TReturn > (TContract proxy, TContract2 proxy2, TContract3 proxy3, Func < TContract, TContract2, TContract3, TReturn >  func,   string  MethodElapsedTimeText, string  MethodErrorText)
        {
            Stopwatch sw 
=   new  Stopwatch();
            sw.Start();
            TReturn returnValue 
=   default (TReturn);
            
try
            {
                returnValue 
=  func(proxy, proxy2, proxy3);
            }
            
catch  (Exception ex)
            {
                
// Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  
+  sw.ElapsedMilliseconds.ToString()  +   " 毫秒 " );
            
return  returnValue;
        }
        
public   static  TReturn Invoke < TContract, TContract2, TContract3, TContract4, TReturn > (TContract proxy, TContract2 proxy2, TContract3 proxy3, TContract4 proxy4, Func < TContract, TContract2, TContract3, TContract4, TReturn >  func,   string  MethodElapsedTimeText, string  MethodErrorText)
        {
            Stopwatch sw 
=   new  Stopwatch();
            sw.Start();
            TReturn returnValue 
=   default (TReturn);
            
try
            {
                returnValue 
=  func(proxy, proxy2, proxy3, proxy4);
            }
            
catch  (Exception ex)
            {
                
// Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText  +  ex.ToString());

            }
            sw.Stop();
            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  
+  sw.ElapsedMilliseconds.ToString()  +   " 毫秒 " );
            
return  returnValue;
        }
    }

    客户端调用:     

代码
string  ComputationTimeText  =   " 取酒店是否在积分广场首页推荐数据耗时: " ;
            
string  ErrorMethodText  =   " 取酒店是否在积分广场首页推荐数据异常: " ;
            
string  conn  =  WebConfig.DaoConfig.MisMasterDBReadConnectionString;
            HotelRecommendInfo 
=  ErrorAndComputationTimeHandler.Invoke < HotelRequestInfo,  string , List < HotelGenericInfo >> (requestInfo, conn, SearchRecommendHotelData, ComputationTimeText, ErrorMethodText);

  AOP的优势:

  1:上述应用范例在没有使用AOP情况下,也能解决,但是,AOP可以让我们从一个更高的抽象概念来理解软件系统。可以这么说:因为使用AOP结构,对于一个大型复杂系统来说可以简化不少代码。

  2:并不是所有的人都需要关心AOP,使得其它开发人员有更多精力去关注自己的业务逻辑。

目录
相关文章
|
1月前
|
缓存 人工智能 监控
AOP:让你的代码像超级英雄一样飞翔
AOP:让你的代码像超级英雄一样飞翔
|
监控 物联网 API
【.NET+MQTT】.NET6 环境下实现MQTT通信,以及服务端、客户端的双边消息订阅与发布的代码演示
MQTT广泛应用于工业物联网、智能家居、各类智能制造或各类自动化场景等。MQTT是一个基于客户端-服务器的消息发布/订阅传输协议,在很多受限的环境下,比如说机器与机器通信、机器与物联网通信等。好了,科普的废话不多说,下面直接通过.NET环境来实现一套MQTT通信demo,实现服务端与客户端的双边消息发布与订阅的功能和演示。
945 0
【.NET+MQTT】.NET6 环境下实现MQTT通信,以及服务端、客户端的双边消息订阅与发布的代码演示
|
3月前
|
Java Maven 数据安全/隐私保护
代码优雅升级,提升开发效率:挖掘Spring AOP配置的学习宝藏!
代码优雅升级,提升开发效率:挖掘Spring AOP配置的学习宝藏!
|
4月前
云效静态代码检测可以检测.net吗?
云效静态代码检测可以检测.net吗?
28 1
|
4月前
|
存储 Java 数据库
spring核心技术(下)--面向切面aop的特点加案例论证
spring核心技术(下)--面向切面aop的特点加案例论证
|
6月前
|
XML Cloud Native Java
Spring AOP使用指南: 强大的面向切面编程技术
Spring AOP使用指南: 强大的面向切面编程技术
44 0
|
7月前
|
算法 编译器 API
|
8月前
|
监控 前端开发 Java
30个类手写Spring核心原理之AOP代码织入(5)
前面我们已经完成了Spring IoC、DI、MVC三大核心模块的功能,并保证了功能可用。接下来要完成Spring的另一个核心模块—AOP,这也是最难的部分。
38 0
|
10月前
|
设计模式 Java Spring
【Spring】核心部分之AOP:通过列举代码例子,从底层刨析,深入源码,轻轻松松理解Spring的核心AOP,AOP有这一篇足以
【Spring】核心部分之AOP:通过列举代码例子,从底层刨析,深入源码,轻轻松松理解Spring的核心AOP,AOP有这一篇足以
|
11月前
|
开发框架 .NET 数据安全/隐私保护
ASP.NET验证控件合集 含代码演示
ASP.NET验证控件合集 含代码演示