65.9K
CodeProject 正在变化。 阅读更多。
Home

自定义异常框架:使用 Enterprise Library 异常处理块

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.95/5 (16投票s)

2008年10月30日

CPOL

3分钟阅读

viewsIcon

71667

downloadIcon

1074

本文演示了一个使用 Enterprise Library 异常处理块创建的自定义异常处理模型的实际工作示例,该模型围绕 MVP 架构构建。

引言

本文演示了如何使用 Microsoft Enterprise Library 异常处理块创建自定义异常层。本文创建的演示项目采用了模型-视图-呈现器 (MVP) 架构,并在其中内置了自定义异常层。

系统要求

  • 安装 Microsoft Enterprise Library .NET 2.0
  • .NET Framework 2.0

重要命名空间

Microsoft.Practices.EnterpriseLibrary.ExceptionHandling

  • Microsoft.Practices.EnterpriseLibrary.Common.dll
  • Microsoft.Practices.ObjectBuilder.dll
  • Microsoft.Practices.EnterpriseLibrary.Common.dll
  • System.Collections.Specialized.dll
  • System.Configuration.Assemblies.dll

自定义异常块的功能

  1. 自定义块根据层来划分异常。例如:数据访问层异常、呈现器层异常、服务层异常等。
  2. 此自定义异常还针对系统层异常,如关键异常。例如:数据库服务器宕机、Web 服务不可用等。
  3. 此自定义异常还处理已处理的异常,并向用户显示自定义消息。例如:在数据库中插入重复记录、从数据库抛出异常,并在 .NET 应用程序中进行处理,然后向上冒泡以显示用户定义的警告消息。因此,这最终区分了警告、错误和异常。对于未处理的系统错误,系统将重定向到一个错误页面。对于警告或操作信息,它将显示在同一个功能屏幕上,以避免中断正常执行。
  4. 此块已集成到模型-视图-呈现器 (MVP) 架构中。

配置设置

配置设置封装了应用程序所需的各种策略。这些策略包括:

  1. 全局策略:识别来自各个层的实际异常。
  2. 传播策略:此策略将层抛出的实际异常传播到主流程。
  3. 自定义策略:呈现器/数据访问/视图/服务。
策略 后处理操作 Layer
1 全局 Project.Practice.MVP.ExceptionHandling
2 传播 NotifyReThrow (通知并重新抛出) System.Exception
3 自定义:呈现器层 ThrowNewException (抛出新异常) Project.Practice.MVP.Presenter
4 自定义:数据访问层 ThrowNewException (抛出新异常) Project.Practice.MVP.DataAccess
5 自定义:视图层 ThrowNewException (抛出新异常) Project.Practice.MVP.Web

Configuration

Project.Practice.MVP.ExceptionHandling: 自定义异常类

带有 MVP 模型的异常处理类的实际表示形式如下所示。

Configuration

下面的类图描绘了异常处理类结构的图。创建了所有自定义异常类的层。这些类本身继承自 `BaseException` 类。

Configuration

Project.Practice.MVP.ExceptionHandling: ApplicationExceptionHandler.cs

在此类中,我们有一个名为 `HandleException` 的方法,该方法实现了 `IExceptionHandler` 接口方法。

namespace Project.Practice.MVP.ExceptionHandling
{
    [ConfigurationElementType(typeof(CustomHandlerData))]
    public class ApplicationExceptionHandler : IExceptionHandler
    {
        private const string UNEXPECTED_ERROR = "Unexpected Error!!";
        public ApplicationExceptionHandler(NameValueCollection ignore)
        {

        }
        #region IExceptionHandler Members
        public Exception HandleException(Exception exception, 
                                         Guid correlationID)
        {
            try
            {
                /* This is Critical Layer Exception.
                For E.g Database Unavailable
                Web Service Unavailable and so on .*/
               
                if (exception.GetType().Equals(
                      typeof(CustomException.CriticalException)))
                {
                    if (HttpContext.Current.Items.Contains("ERROR_MSG"))
                    {
                        HttpContext.Current.Items.Remove("ERROR_MSG");
                    }
                    HttpContext.Current.Items.Add("ERROR_MSG", exception.Message);
                    HttpContext.Current.Server.Transfer(
                                "~/CriticalException.aspx", false);
                }    
                //This is Presenter Layer Exception.
                else if (exception.GetType().Equals(
                          typeof(CustomException.PresenterLayerException)))
                {

                    if ((CustomPage)HttpContext.Current.Handler != null)
                    {
                        ((CustomPage)HttpContext.Current.Handler).Error = 
                            "Presenter Layer Exception :" + 
                            exception.InnerException.Message ;
                    }
                }
                //This is View Layer Exception.
                else if (exception.GetType().Equals(
                          typeof(CustomException.ViewLayerException)))
                {
                    if ((CustomPage)HttpContext.Current.Handler != null)
                    {
                        ((CustomPage)HttpContext.Current.Handler).Error = 
                            "View Layer Exception:" + exception.Message;
                     }
                }
                //This is DataAccess Layer Exception
                else if (exception.GetType().Equals(
                          typeof(CustomException.DataAccesLayerException)))
                {
                    if ((CustomPage)HttpContext.Current.Handler != null)
                    {                      
                        ((CustomPage)HttpContext.Current.Handler).Error = 
                            "DataAccess Layer Exception: "+ exception.Message;
                    }
                }
                //This is SQL DAL Layer Exception
                else if (exception.GetType().Equals(
                             typeof(CustomException.SQLDALException)))
                {
                    if ((CustomPage)HttpContext.Current.Handler != null)
                    {
                        ((CustomPage)HttpContext.Current.Handler).Error = 
                            "SQL Error 101: " + exception.Message;
                    }
                }
                else
                {
                    if ((CustomPage)HttpContext.Current.Handler != null)
                    {
                       //This is Session Expired Exception
                        if ((((CustomPage)
                               HttpContext.Current.Handler).CurrentSession == null))
                        {
                            HttpContext.Current.Items["ERROR_MSG"] = "Access Denied";
                            HttpContext.Current.Server.Transfer(
                                        "~/CriticalException.aspx", false);
                        }
                        //This is General Exception:UN_DEFINED EXCEPTION
                        HttpContext.Current.Server.Transfer(
                                    "~/CriticalException.aspx", false);
                    }
                }
            }
            catch (System.Threading.ThreadAbortException ex)
            {
            }
            catch (Exception ex)
            {
            }
            return exception;
        }

        #endregion
    }
}

Project.Practice.MVP.ExceptionHandling: ExceptionHandleProvider.cs

这是从 Web 页面调用该方法的,当异常冒泡到此处时。

namespace Project.Practice.MVP.ExceptionHandling
{
    public class ExceptionHandleProvider
    {
        public static bool HandleException(Exception exception, string PolicyName)
        {
            bool reThrow = false;
            reThrow = ExceptionPolicy.HandleException(exception, PolicyName);
            return reThrow;
        } 
    }
}

Project.Practice.MVP.DataAccess:DataProvider

这是一个部分类。我们有一个名为 '`DataProvider`' 的部分类,每个模块都有一个不同的文件名。在此方法中,如果异常是数据访问层中的关键异常,它将跨层传播以显示为关键异常;但如果存在数据访问异常,它将通过其他层传播以显示为数据访问层异常。

namespace Project.Practice.MVP.DataAccess
{
    public partial class DataProvider
    {
        public static void ProcessDataAccessLayerException(Exception ex)
        {
            bool reThrow = false;
            if (ex.GetType().Equals(typeof(CriticalException)) == true)
            {
                reThrow = ExceptionPolicy.HandleException(ex, "Propogate Policy");
                if (reThrow)
                {
                    throw ex;
                }
            }
            else if (ex.GetType().Equals(typeof(SQLDALException)) == true)
            {
                reThrow = ExceptionPolicy.HandleException(ex, "Propogate Policy");
                if (reThrow)
                {
                    throw ex;
                }
            }
            else
            {
                reThrow = ExceptionPolicy.HandleException(ex, "DataAccess Layer Policy");
                if (reThrow)
                {
                    throw ex;
                }
            }

        } 

    }
}

现在我们有一个部分类 `DataProvider`,以及一个名为 *MathOperationDataProvider.cs* 的文件模块。

数据访问:抛出异常

namespace Project.Practice.MVP.DataAccess
{
    public partial class DataProvider
    {
        /// <summary>
        /// Get DemandList 
        /// </summary>
        /// <returns></returns>
        public static int AddOperation(int result)
        {
            string error = "SQL_DAL_EXCEPTION";
            try
            {

                if (error == "SQL_DAL_EXCEPTION")
                { 
                    throw new SQLDALException("SQL Store Procedure Error") ;
                }
                if (error == "DATA_ACCESS_LAYER")
                {
                    throw new DataAccesLayerException("Data Not Found Error");
                }
                if (error == "CRITICAL EXCEPTION")
                {
                    throw new CriticalException();
                }
            }
            catch(Exception ex)
            {
                ProcessDataAccessLayerException(ex);
            }
            return result;
        }       
    }
}

Project.Practice.MVP.Presenter

BasePresenter.cs

namespace Project.Practice.MVP.Presenter
{
    public class BasePresenter
    {
        public IServicesProvider m_Service = null;
        public BasePresenter()
        {
            m_Service = new Services.ServicesProvider();
        }
      
        public void ProcessPresenterLayerException(Exception ex)
        {
            bool reThrow = false;
            if (ex.GetType().Equals(typeof(CriticalException)))
            {
                reThrow = ExceptionPolicy.HandleException(
                             ex, "Propogate Policy");
                if (reThrow)
                {
                    throw ex;
                }
            }
            else if (ex.GetType().Equals(typeof(ViewLayerException)))
            {
                reThrow = ExceptionPolicy.HandleException(
                           ex, "Propogate Policy");
                if (reThrow)
                {
                    throw ex;
                }
            }
            else if (ex.GetType().Equals(typeof(DataAccesLayerException)) == true)
            {
                reThrow = ExceptionPolicy.HandleException(
                             ex, "Propogate Policy");
                if (reThrow)
                {
                    throw ex;
                }
            }
            else if (ex.GetType().Equals(typeof(SQLDALException)) == true)
            {
                reThrow = ExceptionPolicy.HandleException(
                            ex, "Propogate Policy");
                if (reThrow)
                {
                    throw ex;
                }
            }
            else
            {
                reThrow = ExceptionPolicy.HandleException(
                               ex, "Presenter Layer Policy");
                if (reThrow)
                {
                    throw ex;
                }
            }
        } 

    }
}

CalculationPresenter.cs

namespace Project.Practice.MVP.Presenter
{
    public class CalculationPresenter : BasePresenter
    {
        #region Public Members
        private ICalculationView m_View = null;
        #endregion

        #region Public Constructor
        public CalculationPresenter(ICalculationView view)
            : base()
        {
            m_View = view;
        }
        #endregion

      
        public void Initialize()
        {
            //Security Check
            //If(user session expires Or login user fails
            //Throw New CriticalLayerException()
        }
        public void AddNumbers()
        {
            try
            {
                m_View.Result= Convert.ToString(AddOperations());
            }
            catch (Exception ex)
            {
                ProcessPresenterLayerException(ex);
            }
        }
        private int AddOperations()
        {
            int result = m_View.Numbers1 + m_View.Numbers2;
            return m_Service.AddOperation(result);
        }
    }
}

Project.Practice.MVP.Web

public partial class Calculation : CustomPage,ICalculationView
{
    #region Private Members
    private CalculationPresenter m_Presenter = null;
    #endregion
    protected void Page_Load(object sender, EventArgs e)
    {
        try
        {
            m_Presenter = new CalculationPresenter((ICalculationView)this);
            if (ViewState["USER_KEY_VALUE"] == null)
            {
                throw new ViewLayerException("Code Behind Exception");
            }
        }
        catch (Exception ex)
        {
            if (ExceptionHandleProvider.HandleException(
                        ex, "Global Policy") == true)
            {
                throw ex;
            }
        }       
    }

    #region ICalculationView Members

    public int Numbers1
    {
        get
        {
            return Convert.ToInt32(txtNumber1.Text);
        }
    }

    public int Numbers2
    {
        get
        {
            return Convert.ToInt32(txtNumber2.Text);
        }
    }

    public string Result
    {
        set
        {
            lblResult.Text = value;
        }
    }

    #endregion
    protected void Button1_Click(object sender, EventArgs e)
    {
        try
        {
            m_Presenter.AddNumbers();
        }
        catch (Exception ex)
        {
            if (ExceptionHandleProvider.HandleException(
                      ex, "Global Policy") == true)
            {
                throw ex;
            }
        }      

    }

    public override string Error
    {
        set {pnlError.Visible = true;
            lblException.Text = value; ; }
    }
}

最终展示

此异常从 ASPX 页面的代码隐藏中抛出或引发。

Configuration

protected void Page_Load(object sender, EventArgs e)
{
    try
    {
        m_Presenter = new CalculationPresenter((ICalculationView)this);
        if (ViewState["USER_KEY_VALUE"] == null)
        {
            throw new ViewLayerException("Code Behind Exception");
        }
    }
    catch (Exception ex)
    {
        if (ExceptionHandleProvider.HandleException(
                   ex, "Global Policy") == true)
        {
            throw ex;
        }
    }
}

Configuration

此异常从数据访问层引发。只需更改错误变量即可测试此层。

string error = "DATA_ACCESS_LAYER";
try
{
    if (error == "SQL_DAL_EXCEPTION")
    { 
        throw new SQLDALException("SQL Store Procedure Not Found") ;
    }
    if (error == "DATA_ACCESS_LAYER")
    {
        throw new DataAccesLayerException("Data Not Found Error");
    }
    if (error == "CRITICAL EXCEPTION")
    {
        throw new CriticalException();
    }
}

Configuration

这是业务层异常,它发生在呈现器层。只需输入截图中的值即可。

public void AddNumbers()
{
    try
    {
        m_View.Result= Convert.ToString(AddOperations());
    }
    catch (Exception ex)
    {
        ProcessPresenterLayerException(ex);
    }
}

这样我们就可以根据需求创建自定义异常了。演示项目需要 Enterprise Library DLL,因此我们需要安装 Microsoft Enterprise Library 才能运行此源代码。

我已经尽力在此提供了足够的信息来解释使用 Enterprise Library 的自定义异常的工作模型。

参考

使用此 UI 界面构建了异常处理块:Enterprise Library 异常处理块

模型-视图-呈现器:MVP 架构

结论

任何修正、批评和建议都非常欢迎。

© . All rights reserved.