一起谈.NET技术,.NET中通过代理实现面向方面编程(AOP)

  上篇文章我说到了在代码中可以利用泛型委托来封装异常处理,这样可以让程序看起来更加清晰,要想完成功能需要调用者调用指定的工厂方法才行,但要想改变某些程序员的编码习惯我想是一件比较困难的事情。有朋友说利用委托来实现异常处理并不算是真正意义上的AOP,因为传统的AOP并不需要客户端做代码结构的变更,最多也就是配置上的问题。但在.net中要想实现AOP,我想最方便的实现机制要属代理机制了,但只要利用代理,在性能上就会造成一定的影响。

  如果开发过分布式服务,像remotion,wcf等,消息都是它们通信的重要手段。客户端通过方法调用形式体现的服务访问需要转换成具体的消息,然后经过编码才能利用传输通道发送给服务端,服务执行的结果也只能以消息的形式返回给调用方。

  这些分布式服务有一共同特点:都通过代理方法间接的调用服务。服务代理,它自身并不提供服务的实现,只是起到一个中介作用,客户端把服务请求发送给服务代理,服务代理再去调真正的服务,同样服务返回时,也是返回给服务代理,再由服务代理返回给客户端。看到这,我想对于实现AOP的拦截就有点眉目了。在.net中,我们可以写自定义的RealProxy来实现AOP的方法拦截功能。

  服务代理通常又分为以下两种:  
  1:透明代理。客户端在跨任何类型的远程处理边界使用对象时,对对象使用的实际上是透明代理。透明代理使人以为实际对象驻留在客户端空间中。它实现这一点的方法是:使用远程处理基础结构将对其进行的调用转发给真实对象。透明代理本身由 RealProxy 类型的托管运行时类的实例收容。RealProxy 实现从透明代理转发操作所需的部分功能。代理对象继承托管对象(例如垃圾回收、对成员和方法的支持)的关联语义,可以将其进行扩展以形成新类。这样,该代理具有双重性质,一方面,它需要充当与远程对象(透明代理)相同的类的对象;另一方面,它本身是托管对象。

  2:真实代理。RealProxy来实现与远程服务进行通信,所以这里就是我们实现AOP的地方。

  下图是透明代理与真实代理以及远程对象的调用关系图:

                            

 

  下图是利用自定义的RealProxy实现AOP方法拦截的原理图:

  

                           

  自定义异常代理类:

  说明:1>自定义的代理类需要继承RealProxy。

     2>从 RealProxy 继承时,必须重写 Invoke方法。

     3>下面代码中的LogManage是一个log4net接口,我们可以把异常统一记录到日志中,供日后分析。

代码
///   <summary>
    
///  Aspect代理,在这个类里面,实现对方法的拦截
    
///   </summary>
     public   class  AspectProxyErrorLog : RealProxy    
    {
        AspectManagedAttribute attr;
        
///   <summary>
        
///  默认构造函数
        
///   </summary>
         public  AspectProxyErrorLog() :  base ()
        {
        }
        
///   <summary>
        
///  构造函数
        
///   </summary>
        
///   <param name="myType"> 被代理的类的类型 </param>
         public  AspectProxyErrorLog(Type myType) :  base (myType)
        {
        }
        
///   <summary>
        
///  构造函数
        
///   </summary>
        
///   <param name="myType"> 被代理的类的类型 </param>
        
///   <param name="obj"> 被代理的对象 </param>
         public  AspectProxyErrorLog(Type myType,MarshalByRefObject obj) :  base (myType)
        {
            target
= obj;
        }
        MarshalByRefObject target;
        ILog LogManage;
        
///   <summary>
        
///  当在派生类中重写时,在当前实例所表示的远程对象上调用在所提供的 IMessage 中指定的方法。 <br />
        
///  WebsharpAspect在这里执行对方法执行的拦截处理
        
///   </summary>
        
///   <param name="msg"> IMessage,包含有关方法调用的信息。 </param>
        
///   <returns> 调用的方法所返回的消息,包含返回值和所有 out 或 ref 参数。 </returns>
         public   override  IMessage Invoke(IMessage msg)
        {
            IMessage retMsg
= null  ;
            IMethodCallMessage methodCall 
=  (IMethodCallMessage)msg;
            IMethodReturnMessage methodReturn 
=   null ;
            
object [] copiedArgs  =  Array.CreateInstance( typeof ( object ), methodCall.Args.Length)  as   object [];
            methodCall.Args.CopyTo(copiedArgs, 
0 );
            
object [] attrs  =   null ;
            CoustomerErrorHandleAttribute ceha 
=   null ;
            
if  (msg  is  IConstructionCallMessage)
            {

 

                IConstructionCallMessage ccm 

=  (IConstructionCallMessage)msg;
                RemotingServices.GetRealProxy(target).InitializeServerObject(ccm);
                ObjRef oRef 
=  RemotingServices.Marshal(target);
                RemotingServices.Unmarshal(oRef);
                retMsg 
=  EnterpriseServicesHelper.CreateConstructionReturnMessage(ccm, (MarshalByRefObject) this .GetTransparentProxy());

 

            }

else
            {
                IMethodCallMessage mcm 
=  (IMethodCallMessage)msg;                
                attrs 
=  methodCall.MethodBase.GetCustomAttributes( typeof (CoustomerErrorHandleAttribute),  false );               
                ceha 
=  LogManagerFactory.GetCoustomerErrorHandleAttribute(attrs, methodCall.MethodBase.Name );
                
if  ( null   !=  ceha)
                {
                    LogManage 
=  ceha.ILogName;
                }
                
try
                {
                    
object  returnValue  =  methodCall.MethodBase.Invoke( this .target, copiedArgs);
                    methodReturn 
=   new  ReturnMessage(returnValue, copiedArgs, copiedArgs.Length, methodCall.LogicalCallContext, methodCall);
                    
                }
                
catch  (Exception ex)
                {
                    
if  ( null   !=  ex.InnerException)
                    {
                        methodReturn 
=   new  ReturnMessage(ex.InnerException, methodCall);
                    }
                    
else
                    {
                        methodReturn 
=   new  ReturnMessage(ex, methodCall);
                    }
                }
                retMsg 
=  methodReturn;

 

            }

if  ( null   !=  methodReturn)
            {
                
if  ( null   !=  methodReturn.Exception )
                {
                    
if  ( null   !=   this .LogManage )
                    {
                        
this .LogManage.Error(ceha .MethodErrorText   +  methodReturn.Exception.ToString());
                    }

 

                }
            }

return  retMsg;

 

        }
    }

  上面只是贴了部分代码,在下一篇中,我会对这部分代码做更加详细的分析。

转载于:https://www.cnblogs.com/waw/archive/2011/08/29/2158732.html

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计,皆可应用在项目、毕业设计、课程设计、期末/期/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值