EsbAOP应用--异常关闭器

    以我自己的异常处理经验,我通常会在UI事件处理函数或线程启动函数中截获所有的异常,然后对截获的异常作特定的处理--很多情况下,是显示一个错误信息给用户,或记录异常日志!在这“很多情况下”,我都需要做相同的工作,首先是用try...catch把UI事件处理函数或线程启动函数中的所有代码围起来,然后,可能就是MessageBox.Show(ex.Message)或其它的处理。
    大家已经想到了,这类事情正好可以使用AOP来完成。本文将在前文介绍的EsbAOP的基础上来开发一个异常关闭器方面--ExceptionCloseerAspect,该方面修饰UI操作或修饰background线程的启动函数,用于控制是否拦截被修饰的方法抛出的异常,如果拦截,则对异常进行用户自定义处理,然后关闭该异常。
    关于ExceptionCloseerAspect要注意以下几个方面:
    (1)在UI操作时或后台线程中,经常其中会访问数据库或网络,为了截获这些异常,需要在每个UI的事件处理函数中写try...catch, 如果使用ExceptionCloseerAspect,则就不用在写try-catch了,ExceptionCloseerAspect会自动帮我们把异常截获,然后关闭它。
   (2)ExceptionCloseerAspect通常用于系统结构的最上层,比如UI层、或background线程的启动函数处。而且正好这些函数的返回值为void。
   (3)用户可以通过实现IExceptionHandler自定义异常处理方案,比如记录异常日志、弹出消息框通知使用者等。
   (4)注意,一般UI从Form继承,所以无法再从ContextBoundObject继承,也就无法对其使用Aspect,所以需要把最上层的逻辑封装在一个单独的类中==》而这有助于UI与逻辑的分离! 

    从前面的分析已经看到,线程有两种类型,一是主线程(通常为UI线程),一是后台线程,对于不同线程抛出的异常,用户可能需要作不同的处理,所以,我们使用枚举来定义线程类型:

    /// <summary>
    /// ExceptionCloseType 异常发生所在线程的类型
    /// </summary>
    public enum ExceptionHostType
    {
        NotSetted ,UIThread ,BackGroundThread
    }

    
    而为了使用户有机会处理抛出的异常,我们提供了IExceptionHandler接口:

    /// <summary>
    /// IExceptionHandler 在关闭异常之前,用户可以通过自定义的IExceptionHandler来处理异常,比如记录为日志或显示错误信息给用户
    /// </summary>
    public interface IExceptionHandler
    {
        void HandleException(Exception ee ,ExceptionHostType hostType) ;
    }

    在这些基础之上,我们就可以来实现ExceptionCloseerAspect了。从前文可以知道,ExceptionCloseerAspect只需要实现IAspect接口就可以了。现在给出其实现:

public class ExceptionCloseerAspect :IAspect
    {
        public ExceptionCloseerAspect()
        {            
        }

        #region IAspect 成员
        public void PreProcess(IMethodCallMessage requestMsg, object aspectClassArgument, object aspectMethodArgument)
        {
            
        }

        public void PostProcess(IMethodCallMessage requestMsg, ref IMethodReturnMessage respond, object aspectClassArgument, object aspectMethodArgument)
        {            
            if(respond.Exception == null)
            {
                return ;
            }

            Type HandlerType = (Type)aspectClassArgument ;
            Type destType    = typeof(IExceptionHandler) ;
            if(! destType.IsAssignableFrom(HandlerType))
            {
                return ;
            }

            IExceptionHandler exceptionHandler = (IExceptionHandler)Activator.CreateInstance(HandlerType) ;
            if(aspectMethodArgument != null)
            {
                exceptionHandler.HandleException(respond.Exception ,(ExceptionHostType)aspectMethodArgument) ;
            }
            else
            {
                exceptionHandler.HandleException(respond.Exception ,ExceptionHostType.NotSetted) ;
            }

            //修改返回结果,关闭异常
            respond = new ReturnMessage(null ,requestMsg) ;
        }

        #endregion
    }

    上面的实现有几点需要说明:
(1)ExceptionCloseerAspect的aspectClassArgument是实现了IExceptionHandler接口的类型
(2)ExceptionCloseerAspect的aspectMethodArgument是ExceptionHostType枚举值之一。
(3)注意PostProcess方法实现的最后一句,是AOP修改了方法调用的结果,从而关闭了异常。

    在实现了异常关闭器之后,我们就可以来小试牛刀了。首先,我们需要实现IAspectProcessorWrap接口来把ExceptionCloseerAspect所需要的资源反应出来:

public class ExceptionClosserWrap :IAspectProcessorWrap
    {
        #region IAspectProcessorWrap 成员

        public Type AspectProcessorType
        {
            get
            {                
                return typeof(ExceptionCloseerAspect);
            }
        }

        public object AspectClassArgument
        {
            get
            {
                return typeof(ExceptionHandler) ;
            }
        }

        public EnterpriseServerBase.Aop.MultiAspect.AspectSwitcherState DefaultAspectSwitcherState
        {
            get
            {                
                return AspectSwitcherState.On;
            }
        }

        #endregion
    }

    我们还需要实现IExceptionHandler来处理异常:

public class ExceptionHandler :IExceptionHandler
    {
        #region IExceptionHandler 成员

        public void HandleException(Exception ee, ExceptionHostType hostType)
        {
            if(hostType == ExceptionHostType.UIThread)
            {
                MessageBox.Show(ee.Message + "UI Thread !") ;
            }

            if(hostType == ExceptionHostType.NotSetted)
            {
                MessageBox.Show(ee.Message + " host thread not setted !") ;
            }

            if(hostType == ExceptionHostType.BackGroundThread)
            {
                MessageBox.Show(ee.Message + " background thread !") ;
            }
        }

        #endregion

    }

    前面的代码很容易明白,异常处理只是将异常信息显示给用户。现在来看看如何使用ExceptionCloseerAspect。需要再次强调的是,ExceptionCloseerAspect通常作用于UI事件处理函数或线程启动函数。我们已一个UI事件处理函数作为例子,首先要保证UI与业务逻辑分离,所以,我将业务逻辑封装在MyBusiness类中:

    [Aspect(typeof(ExceptionClosserWrap))]
    public class MyBusiness :ContextBoundObject
    {
        [AspectSwitcher(typeof(ExceptionClosserWrap) ,true ,ExceptionHostType.UIThread)]
        public void OnButton1Click()
        {
            throw new Exception("sky test exception !") ;
        }

        [AspectSwitcher(typeof(ExceptionClosserWrap) ,true)]
        public void OnButton2Click()
        {
            throw new Exception("sky2 test exception !") ;
        }

        [AspectSwitcher(typeof(ExceptionClosserWrap) ,true ,ExceptionHostType.BackGroundThread)]
        public void SkyThread()
        {
            throw new Exception("backGround thread exception !") ;
        }
    }

     而在所有的UI事件处理函数中,都将调用MyBusiness对应的方法,如:

 

private void button1_Click(object sender, System.EventArgs e)
        {
            this.myBusiness.OnButton1Click() ;
        }

        private void button2_Click(object sender, System.EventArgs e)
        {
            this.myBusiness.OnButton2Click() ;
        }

        private void button3_Click(object sender, System.EventArgs e)
        {
            Thread thread = new Thread(new ThreadStart(this.myBusiness.SkyThread)) ;
            thread.Start() ;
        }

     大家可以仿照上面的例子自己写一个,看看运行的结果,下面也给出示例源码下载!

    示例下载

 

 

时间: 2024-09-26 02:44:43

EsbAOP应用--异常关闭器的相关文章

Oracle 9i数据库异常关闭后的启动

Oracle shutdown的时候突然断电,导致使用sql/plus启动时无法连接到数据库,具体描述为: connection can not permitted, shut in progress. 到dos 提示符 键入: c:\> sqlplus /nolog 显示: sql/plus: Realease9.0.2--..all rights reserved sql> connect /as sysdba 显示已连接至空闲例程 sql>startup 显示shutdown in

系统-浏览器异常关闭或关闭选项卡后怎么清除该登录用户信息

问题描述 浏览器异常关闭或关闭选项卡后怎么清除该登录用户信息 现在我的系统可以实现阻止同一用户在不同浏览器上的登录,允许不同用户在同一浏览器上的登录,可一旦不是正常退出,直接关闭选项卡或直接关闭浏览器的话,用户不能在重新登录了,求教. 解决方案 判断用户的在线状态 获得用户登陆状态不用说了,判断离开的话就有一点问题了,如果说用户都是按照设计者的规定触发退出事件离开的话那就没什么难度了,但是用户的离开方式多种多样,怎么在用户非法离开的时候即时的判断离开呢?最常见的非法离开就是关闭浏览器了. 复制代

visual studio 2010-vs2010新建类库异常关闭,然后程序报错

问题描述 vs2010新建类库异常关闭,然后程序报错 电脑重装系统了,把之前的项目拷出来了.装完系统,装上vs2010项目打不开.DAL里面缺少DAL.dll.还有别的地方缺少.dll文件.重建项目,web文件没事,新建类库就出现问题,vs2010异常关闭.然后重新生成文件就提示"错误 1 源文件"E:CeShiCeShi11-10DALClass1.cs"未能打开("此实现不是 Windows 平台 FIPS 验证的加密算法的一部分.") DAL&quo

有酬工作,Domino服务异常关闭处理

问题描述 有酬工作,Domino服务异常关闭处理,具体联系QQ:18288522 解决方案 解决方案二:此问题处理了么?

google maps-android应用程序异常关闭

问题描述 android应用程序异常关闭 我用android创建Google Map应用程序,当我运行程序时,没有问题.但是在仿真器上运行时,出现以下错误: The application has stopped unexpectedly. Please try again. 还有别的调试模式吗?那样是不是才能找到实际的问题所在.开发的环境配置是 Eclipse 和 AVD. 解决方案 我提供一个Eclipse里调试方式,希望能帮上你.现在android程序中的任意代码行中放断点.现在通过Pac

TCP异常关闭研究分析

研究测试TCP断开和异常的各种情况,以便于分析网络应用(比如tconnd)断网的原因和场景,帮组分析和定位连接异常掉线的问题,并提供给TCP相关的开发测试人员作为参考. 各个游戏接入都存在一定的掉线问题,而且有的游戏项目的掉线比例还比较高,现在互娱自研游戏的网络接入基本上都用的是tconnd和ProtocalHandler组件(该组件请参考附件的<TSF4G_ProtocalHandler开发指导手册>),因此参与其掉线原因分析和研究. 在参与A项目的掉线问题研究分析过程中,tconnd增加了

Oracle 9i 数据库异常关闭后的启动_oracle

正在看的ORACLE教程是:Oracle 9i 数据库异常关闭后的启动. Oracle 数据库启动  Oracle shutdown的时候突然断电,导致使用sql/plus启动时无法连接到数据库,具体描述为: connection can not permitted, shut in progress. 到dos 提示符 键入:  c:\> sqlplus /nolog  显示: sql/plus: Realease9.0.2--..all rights reserved sql> conne

Oracle9i数据库异常关闭后的启动_oracle

正在看的ORACLE教程是:Oracle9i数据库异常关闭后的启动.Oracle shutdown的时候突然断电,导致使用sql/plus启动时无法连接到数据库,具体描述为: connection can not permitted, shut in progress. 到dos 提示符 键入: c:\> sqlplus /nolog 显示: sql/plus: Realease9.0.2--..all rights reserved sql> connect /as sysdba 显示已连接

我心中的核心组件(可插拔的AOP)~第四回 异常拦截器

之前说过有关拦截器的文章,第二回  缓存拦截器,事实上,在那讲里说的最多是AOP和缓存组件,对于拦截的概念并没有详细的说明,这一讲,不说AOP,主要说一下拦截器,拦截器Interception,主要是在方法执行前或者执行后,动态添加一些行为,而这个行为主要包含缓存,日志,异常处理及你可以想到的所有的一切,呵呵. 这一讲是异常拦截器,它的主要意义在于,当你的一个方法被执行时,你可以通过配置文件去管理这个方法执行前与执行后是否附加统一异常处理行为. 拦截器组件我们还是用Unity.Intercept