使用动态代理,提高工作效率

    动态代理的一个最主要的应用场合就是实现AOP - 截获方法调用,加入自己的预处理、后处理或Around处理。
    我在ESBasic.Emit中实现了对这些截获的支持。
    首先,介绍两个截获者:
    ///   <summary>
    
///  IMethodInterceptor 对方法进行截获并加入预处理和后处理。
    
///   </summary>
     public   interface  IMethodInterceptor
    {
        
void  PreProcess(InterceptedMethod method);

        
void  PostProcess(InterceptedMethod method , object  returnVal);
    }
    IMethodInterceptor 很容易理解,用于为截获插入预处理、后处理。这个非常容易理解。
      ///   <summary>
    
///  IAroundInterceptor 对方法进行Around截获处理。注意,必须要触发目标方法的调用。
    
///   </summary>
     public   interface  IAroundInterceptor
    {
        
object  AroundCall(InterceptedMethod method);
    }
    Around处理由 IAroundInterceptor完成。什么是Around处理了?比如,我们想捕获目标方法的异常,需要使用TryCatch将目标方法Around起来,这就是Around处理的一个例子。
    在上面的接口方法中都有一个参数 InterceptedMethod,它 封装了被截获的目标方法的基本信息。
public   sealed   class  InterceptedMethod
    {
        
#region  Ctor
        
public  InterceptedMethod() { }
        
public  InterceptedMethod( object  _target, MethodInfo _method,  object [] paras)
        {
            
this .target  =  _target;
            
this .method  =  _method;
            
this .arguments  =  paras;
        } 
        
#endregion

        
#region  Method
        
private  MethodInfo method;
        
///   <summary>
        
///  Method 被截获的目标方法
        
///   </summary>
         public  MethodInfo Method
        {
            
get  {  return  method; }
            
set  { method  =  value; }
        }
        
#endregion

        
#region  Target
        
private   object  target;
        
///   <summary>
        
///  Target 被截获的方法需要在哪个对象上调用。
        
///   </summary>
         public   object  Target
        {
            
get  {  return  target; }
            
set  { target  =  value; }
        } 
        
#endregion

        
#region  Arguments
        
private   object [] arguments;
        
///   <summary>
        
///  Arguments 调用被截获的方法的参数
        
///   </summary>
         public   object [] Arguments
        {
            
get  {  return  arguments; }
            
set  { arguments  =  value; }
        } 
        
#endregion        

        
#region  Invoke
        
///   <summary>
        
///  Invoke 执行目标方法
        
///   </summary>         
         public   object  Invoke()
        {
            
return   this .method.Invoke( this .target,  this .arguments);
        } 
        
#endregion
    }

    好,如何使用ESBasic.Emit来创建动态代理了?很简单,你只需要调用
public   static  TInterface CreateAopProxy < TInterface > ( object  origin, IMethodInterceptor methodInterceptor, IAroundInterceptor aroundInterceptor)
    如果不需要某种截获处理,对应的参数传入null即可。
    举个例子,我们需要使用动态代理截获IComputer所有方法调用抛出的异常,并记录日志。IComputer定义如下:
    public   interface  IComputer 
    {
        
int  Add( int  a,  int  b);      
    }

    
public   class  Computer : IComputer
    {
        
public   int  Add( int  a,  int  b)
        {
            
throw   new  Exception( " TestException " );
            
return  a  +  b;
        }   
    } 
    我可以使用Around截获者来截获异常,所以我实现一个自己的 IAroundInterceptor
    public   class  ExceprionAroundInterceptor : IAroundInterceptor
    {
        
#region  IAroundInterceptor 成员
        
public   object  AroundCall(InterceptedMethod method)
        {
            
try
            {
                
return  method.Invoke();
            }
            
catch  (Exception ee)
            {
                ee 
=  ee;
                
// .. log Exception

                
throw ;
            }
        }
        
#endregion
    }
    现在,我们可以这样获得针对IComputer的动态代理的引用:
    IComputer proxy  =  ESBasic.Emit.Application.DynamicProxyFactory.CreateAopProxy < IComputer > ( new  Computer() , null  , new  ExceprionAroundInterceptor()) ;
    proxy.Add(
1 2 );
    这样就ok了,Add方法抛出的异常会被 ExceprionAroundInterceptor截获。

    最后,提醒一下,如果你让Computer不从IComputer继承,运行结果也一样。你应该已经看到 DynamicProxyFactory.CreateAopProxy方法的第一个参数是object类型,而不是泛型T,这说明只要对应的object包含了和目标接口一样的方法(签名完全一致)就可以 -- 这就是所谓的“换脸”能力,可以在 这里看到更详细的说明。
    由于动态代理是使用Emit发射实现,所以效率上来说,和你手写的代码是没有区别的。

     下载 ESBasic.Emit.dll。

    











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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值