一起谈.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;

 

        }
    }

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

时间: 2024-09-21 02:17:02

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

.NET中通过代理实现面向方面编程(AOP)

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

一起谈.NET技术,使用WCF实现SOA面向服务编程——使用AJAX+WCF服务页面开发

在上一篇讲到,如果将BLL层的每一个类都转化为*.svc,这是一个不实在的想法.它会使服务变化复杂,难于管理. 这时候,我们第一时间想到的是23个简单开发模式中的Factory,在这里,Factory正好派上用场.我们把这个Factory称之为管道(pipeline) ,通过这个管道客户端可以随意调用服务器BLL层里面的类. (关于管道的概念,建议参考Cory Isaacson的杰作<多核应用架构关键技术-软件管道与soa>) 当你使用B/S方式开发UI层时,只要了解此开发模式,使用Ajax加

一起谈.NET技术,使用WCF实现SOA面向服务编程——简单的WCF开发实例

前面为大家介绍过WCF的特点,现在再讲解一下WCF基础概念. 在WCF里,各个Application之间的通信是由EndPoint来实现的,EndPoint是WCF实现通信的核心要素.一个WCF Service可由多个EndPoint集合组成,每个EndPoint只能有一种绑定,就是说EndPoint就是通信的入口,客户端和服务端通过 EndPoint交换信息. <service name = " " >< endpoint address = ""

Spring中反向控制和面向切面编程的应用

引言 在J2EE的整个发展历程中,现在正是一个非常时刻.从很多方面来说,J2EE都是一个伟大的成功:它成功地在从前没有标准的地方建立了标准:大大提升了企业级软件的开放程度,并且得到了整个行业和开发者的广泛认可.然而,J2EE在一些方面已经开始捉襟见肘.J2EE应用开发的成本通常很高.J2EE应用项目至少和从前的非J2EE项目一样容易失败--如果不是更容易失败的话.这样的失败率高得让人难以接受.在这样的失败率之下,软件开发几乎变成了碰运气.而在J2EE遭遇失败的场景中,EJB通常都扮演着重要的角色

一起谈.NET技术,中软面试题-最新

      中软的面试比较经典,也比较严格,一般有四轮,类似于微软的面试.中软面过以后,根据项目组,会推到美国微软那边运用live meeting & con-call 再面一次.以下是我的面试题及个人的小分析,拿出来和大家share一下.希望更多的人能过这个坎.如有什么问题,可以一起交流.直接进入主题:  1. English communication. (sale yourself, project information, your interesting,and how to deal

浅析设计模式中的代理模式在C++编程中的运用_C 语言

由遇到的问题引出代理模式 至少在以下集中情况下可以用代理模式解决问题: 创建开销大的对象时候,比如显示一幅大的图片,我们将这个创建的过程交给代理去完成,GoF 称之为虚代理(Virtual Proxy): 为网络上的对象创建一个局部的本地代理,比如要操作一个网络上的一个对象(网络性能不好的时候,问题尤其突出),我们将这个操纵的过程交给一个代理去完成,GoF 称之为远程代理(Remote Proxy): 对对象进行控制访问的时候,比如在 Jive 论坛中不同权限的用户(如管理员.普通用户等)将获得

一起谈.NET技术,.NET 4 并行(多核)编程系列之二 从Task开始

前言:我们一步步的从简单的开始讲述,还是沿用我一直的方式:慢慢演化,步步为营. 本篇文章的议题如下: 1.Task基础介绍 2.Task的创建 3.获取Task的执行结果 4. 补充细节 1.Task基础介绍 首先我们还是来看看一段简单的代码: 这里展示的只是一段简单的代码,不能显示出并行编程的特点.但是我们还是从最基本的开始看,慢慢进入深一点的话题. 如果你曾经用过.NET 中的多线程编程,比较一下,就会发现:这段代码虽然在底层还是使用了多线程,但是写法上却简化了很多,一行代码就实现了一个并行

一起谈.NET技术,.NET 4 并行(多核)编程系列之一入门介绍

本系列文章将会对.NET 4中的并行编程技术(也称之为多核编程技术)以及应用作全面的介绍. 本篇文章的议题如下: 1. 并行编程和多线程编程的区别. 2. 并行编程技术的利弊 3. 何时采用并行编程 1.并行编程和多线程编程的区别. 1.1并行编程. 现在随着多核计算机的普及,并行编程技术,也就是多核编程技术也逐渐称为开发的主流.为此,在.NET 4 中就引入了"并行编程".在.NET 4 中一些列的Library和类为并行编程提供了支持,如: Task Parallel Librar

一起谈.NET技术,由扩展方法引申出的编程思维

1. Helper大爆炸 .NET Framework为我们提供了丰富的类库,但是这并不是万能地,在大部分的时间,我们都需要为我们的项目特殊定制我们的通用类库. 常常,我们都可以构造一个类,类里封装一些方法.但是对于很多时候,我们并没有办法提取出这样一个类,举一个小例子,我们在很多时候,需要把url给保存到数据库里,作为一个唯一标识,但是我们知道url所占空间很大,如果用url来建立索引的话是非常耗费空间,而且影响效率的,那么我们最常用的办法就是把url做一个Hash来作为索引的替代品. 这个时