2017-07-03 68 views
0

当我查看.NET Framework中的方法时,它可能会抛出几个可能的异常。提前规划异常处理策略

从规划的角度来看,我需要问什么来规划和处理这些例外情况?我明白,取决于异常的影响,这将影响在UI层显示它。例如,如果后端对用户体验不透明的进程抛出异常,那么您不希望向用户显示该进程,因为他/她不知道该进程是什么。

感谢

+0

托管VS编译器把默认的异常处理程序在执行堆栈所以在代码中的任何未处理的异常得到由默认的处理程序捕获的顶部,所以把一个例外hanlder在主会捕获所有异常没有被代码中的其他处理程序捕获,并会停止默认处理程序显示不需要的异常消息。 – jdweng

回答

0

你通常有一个商业逻辑层在你的应用程序,而且你包裹在安全的调用该库中的方法。这些方法甚至可以说出他们可以抛出什么异常,并且如果您愿意,您可能希望以独特的方式处理这些异常。

这里有几个类,可以同时处理突发和自定义异常的例子:

class Program 
{ 
    static void Main(string[] args) 
    { 
     MethodInvokationResult result = SafeActionInvokator.HandleSafely(() => 
     { 
      MyFakeBusinessEngine.DivideTwoNumbers(5, 0); 
     }); 
     if (result.Exception is System.DivideByZeroException) 
     { 
      Debug.WriteLine($"A divide by zerp exception was caught"); 
     } 
     else if (!result.Success) 
     { 
      Debug.WriteLine($"An unknown error occured."); 
     } 
    } 
} 

^你可以看到,你可以用呼叫,并在合理的方式处理它们。

public class MethodInvokationResult 
{ 
    public bool Success { get; set; } 
    public Exception Exception { get; set; } 
} 

^一个简单的结果类

public static class MyFakeBusinessEngine 
{ 
    /// <summary> 
    /// Divides two numbers 
    /// </summary> 
    /// <param name="a">numerator</param> 
    /// <param name="b">denominator</param> 
    /// <returns>the result</returns> 
    /// <exception cref="System.DivideByZeroException">When b is zero, divide by zero exception is thrown.</exception> 
    public static int DivideTwoNumbers(int a, int b) 
    { 
     return a/b; 
    } 
} 

^A有据可查的方法,甚至告诉其他开发人员,预计将抛出什么异常

public static class SafeActionInvokator 
{ 
    /// <summary> 
    /// Executes a method, and if any exception is thrown, will log the error and swallow the exception. 
    /// </summary> 
    /// <param name="methodToExecute"></param> 
    public static MethodInvokationResult HandleSafely(Action methodToExecute) 
    { 
     try 
     { 
      methodToExecute.Invoke(); 
      return new MethodInvokationResult() 
      { 
       Exception = null, 
       Success = true 
      }; 
     } 
     catch (Exception ex) 
     { 
      Debug.WriteLine($"{ex}"); 
      return new MethodInvokationResult() 
      { 
       Exception = ex, 
       Success = false 
      }; 
     } 
    } 
} 

^该方法的包装你调用,将其封装在try catch中允许您以相同的方式处理所有异常,或者将您想要的任何自定义逻辑放在那里。

这可以扩展为一个可以返回任何实际结果值的调用。你可以创建一个通用的结果类,而不是我已经展示的简单结果类。

最后!至于您的实际问题,我会在整个应用程序中创建这些层,并重新引发包含严重等级的任何异常。这些会传播到您的UI层,您可以根据严重性选择要执行的操作。

也许就是这样!

public class MajorException : Exception { } 
public class MediumException : Exception { } 
public class MinorException : Exception { } 
public class UserError : Exception { } 

希望这有助于!

+0

这是一个非常方便的技术,谢谢!例如,如果应用程序中存在一个关键文件(如配置文件),然后应用程序尝试打开它,那么这将是一个主要(或致命)异常。在那种情况下,我会关闭应用程序。我期望做的是做一个流程图,根据它们的性质描述我应该采取的异常行为。 – dotnetdev

+0

流程图eh?我强烈推荐yEd Graph Editor - 完全免费,它很棒。我在工作中使用它!只要您可以定义您期望可以处理的异常,就需要人类的大脑力量来认识一行代码或代码块可能出错,例如您提到的文件访问。如果你能预料到,你可以处理它。哎呀,你可以预料到总崩溃,只要异常安全处理,你的应用就可以继续。 –

+0

我应该补充......你可能想要考虑在失败时应该怎么做,这可能意味着回滚以前的操作。这可能会让人毛骨悚然,但有一个你可以使用的UnitOfWork模式,可能利用DotNet框架提供的交易模式......我离题了。 –

0

我想把它写成一个评论,但它是长注释文本框...

  1. 但也有例外是重要的,以显示用户,因为他们可以自己处理它,用于例如:文件名是非法的。

  2. 有一些例外,我觉得很重要,因为他们(用户)会像我的QA团队一样展示用户,例如:某些方法不会更新GUI,他们可能会得出结论:他们应该进一步报告,他们会告诉我的例外,我会发现我的阵列超出界限...

  3. 也有例外,推动他们的用户只会混淆他们,像你说的

“他/她本来就是不知道什么是”

例如,例如:

“如果在不透明的后端进程抛出异常”。

那些我为自己节省了异常(在数据库..)..
我总是提醒自己,最终用户有不同的心理比较开发商( - :

我希望我理解你的问题正确的方式。

+0

是的,你做了感谢,很高兴知道你的用户的观众! – dotnetdev