异常处理与用户友好的错误消息

在软件开发过程中,异常处理是一个重要的环节。良好的异常处理不仅能帮助开发者快速定位问题,还能提升用户体验。当用户在使用应用程序时遇到错误,一个清晰、友好的错误消息可以让用户更好地理解问题所在,从而向支持团队提供准确的信息,帮助快速解决问题。

然而,许多应用程序在遇到错误时,往往只显示一个通用的错误消息,如“技术问题,请与管理员联系”,这样的消息对用户来说并不友好,也不利于问题定位。为了解决这个问题,可以开发一个小工具,通过堆栈跟踪(stacktrace)和自定义属性来生成具体的错误消息。这样,就不需要在每个方法上都实现try-catch块。

实现方法

要实现这种方法,需要在所有方法上放置一个自定义属性,该属性描述了方法的实际功能。这样,在异常发生时,可以为每个步骤生成消息。

需要注意的是,由于这个工具会从整个堆栈跟踪中提取方法描述,可能会暴露业务流程给最终用户。因此,这种方法更适合内部工具使用。如果不希望透露任何操作,可以不为特定方法指定描述。

已知问题

在发布版本中,可能无法获取所有步骤。如果确实需要所有步骤,可以通过更改构建配置设置来实现。

具体操作如下:

Project-> Properties -> Build Configuration = Release Optimized Code = false (unchecked) Advanced build settings: Debug Info: full

以下是主应用程序的源代码示例:

class Program { static void Main(string[] args) { try { var loanValidator = new LoanValidator(); loanValidator.CheckLoanApplication(); } catch (Exception ex) { string exceptionMessage = ExceptionHelper.GetDetailMessage(ex); Console.Write(exceptionMessage); Console.Read(); } } }

以下是自定义属性的源代码示例:

public class MethodDescription : Attribute { public MethodDescription(string description) { this.Description = description; } public string Description { get; set; } }

以下是贷款验证器的源代码示例:

public class LoanValidator { [MethodDescription("Validating loan application")] public bool CheckLoanApplication() { bool isValidPersonalDetail = CheckPersonalDetail(); bool isValidEmploymentDetail = CheckEmploymentDetail(); bool isValidBankAccountDetail = CheckBankAccountDetail(); if (isValidPersonalDetail && isValidEmploymentDetail && isValidBankAccountDetail) return true; else return false; } [MethodDescription("Checking personal detail")] private bool CheckPersonalDetail() { return true; } [MethodDescription("Checking employment detail")] private bool CheckEmploymentDetail() { return true; } [MethodDescription("Checking bank account detail")] private bool CheckBankAccountDetail() { CheckAnyOutstanding(); return true; } [MethodDescription("Checking outstanding detail from common web server")] private bool CheckAnyOutstanding() { throw new WebException(); return true; } } public class ExceptionHelper { public static string GetDetailMessage(Exception ex) { StringBuilder messageBuilder = new StringBuilder(); Type attributeType = typeof(MethodDescription); int step = 1; var attributes = GetStackTraceSteps<MethodDescription>(ex); if (attributes != null && attributes.Count > 0) messageBuilder.AppendLine(string.Format("Sorry there is a problem while processing step {0}:", attributes.Count)); foreach (var attribute in attributes) { messageBuilder.Append(string.Format("Step {0}: {1}", step.ToString(), attribute.Description)); messageBuilder.AppendLine(); step++; } messageBuilder.AppendLine(); string formatedMessage = string.Format("{0}Error Description : {1}", messageBuilder.ToString(), ex.Message); return formatedMessage; } public static List<T> GetStackTraceSteps<T>(Exception ex) { List<T> traceSteps = new List<T>(); Type attributeType = typeof(T); StackTrace st = new StackTrace(ex); if (st != null && st.FrameCount > 0) { for (int index = st.FrameCount - 1; index >= 0; index--) { var attribute = st.GetFrame(index).GetMethod().GetCustomAttributes(attributeType, false).FirstOrDefault(); if (attribute != null) { traceSteps.Add((T)attribute); } } } return traceSteps; } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485