天天看點

EsbAOP應用--異常關閉器

    關于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接口:

    /// IExceptionHandler 在關閉異常之前,使用者可以通過自定義的IExceptionHandler來處理異常,比如記錄為日志或顯示錯誤資訊給使用者

    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))

            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

                return typeof(ExceptionHandler) ;

        public EnterpriseServerBase.Aop.MultiAspect.AspectSwitcherState DefaultAspectSwitcherState

                return AspectSwitcherState.On;

    我們還需要實作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 !") ;

    前面的代碼很容易明白,異常處理隻是将異常資訊顯示給使用者。現在來看看如何使用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() ;

     大家可以仿照上面的例子自己寫一個,看看運作的結果,下面也給出示例源碼下載下傳!