2016-09-28 23 views
1

我有一个C#代码使用可以抛出异常的外部库。 在我的代码三个部分,我想处理这些异常的方式如下:如何分解try/catch代码?

try { 
    CallOtherLibrary(); 
} 
catch(ExceptionA) { 
    ProcessErrorA(); 
} catch(ExceptionB) { 
    ProcessErrorB(); 
} 

现在我认为复制粘贴此代码是一个代码味道。 一种可能的解决方法是创建一个将操作作为参数的方法,并执行try/catch。但它迫使我复制每个调用try/catch的方法,这会导致更多的代码,不太可读。

考虑到我无法改变外部库的行为,干净的方式来处理这个问题是什么?

+2

你要执行完全相同的代码来响应完全相同的异常,只有在对其他库的不同调用期间才会发生?我的意思是,“ExceptionA”在所有案例中都有相同的答案吗? –

+0

全局异常处理程序可能有帮助,如果它适合你的上下文,它的异常处理大致相同(如日志记录等)。 –

回答

2

您可以制作一个Dictionary<Type, Action> exceptionHandlers,然后在catch块中调用 exceptionHandlers[exception.GetType()]()

void ProcessErrorA() { } 

    void Main() 
    { 
     Dictionary<Type, Action> exceptionHandlers = new Dictionary<Type, Action>(); 
     exceptionHandlers.Add(typeof(NullReferenceException), ProcessErrorA); 

     try{} 
     catch (Exception e) 
     { 
      if (exceptionHandlers.ContainsKey(e.GetType())) 
      { 
       exceptionHandlers[e.GetType()](); 
      } 
      else 
      { 
       // We don't have any handler for this exception. 
      } 
     } 
    } 
2

您正在寻找外星文库的包装。在C#中,这通常通过使用interface以及作为Facade/Adapter的方法来完成。

您创建了一个充当适配器的新类,实现了适配器接口,并且在实现的方法中,您将获得问题中提到的代码。然后,通过调用新创建的适配器的方法来替换原始代码,然后在代码库中使用该代码。

有一个适配器的好处是你不拥有和使用这个适配器的库不必重写自己的逻辑,如果外部库的方法签名在将来会改变,而只是改变它在适应层,你就全部重新设置。

0

也许你可以做这样的事情(适应自己使用):

class Program 
{ 
    public int Divide_InExternalLib(int a, int b) 
    { 
     Console.WriteLine(string.Format("a={0}, b={1}", a, b)); 
     int result = a/b; 
     Console.WriteLine(string.Format("Result = {0}", result)); 
     return result; 
    } 


    public void CallExternalFunction(Action funct) 
    { 
     try 
     { 
      funct.Invoke(); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(string.Format("Exception caught: {0}", ex.ToString())); 
     } 
    } 

    static void Main(string[] args) 
    { 
     var p = new Program(); 
     int a = 6; 
     int b = 2; 
     p.CallExternalFunction(() => { p.Divide_InExternalLib(a, b); }); 
     b = 0; 
     p.CallExternalFunction(() => { p.Divide_InExternalLib(a, b); }); 

     Console.ReadLine(); 
    } 
} 

输出

a=6, b=2 
Result = 3 
a=6, b=0 
Exception caught: System.DivideByZeroException: Attempted to divide by zero. 
    at GenericExceptionHandling.Program.Divide_InExternalLib(Int32 a, Int32 b) in 
c:\users\siebiers\documents\visual studio 2015\Projects\GenericExceptionHandlin 
g\GenericExceptionHandling\Program.cs:line 16 
    at GenericExceptionHandling.Program.<>c__DisplayClass2_0.<Main>b__1() in c:\u 
sers\siebiers\documents\visual studio 2015\Projects\GenericExceptionHandling\Gen 
ericExceptionHandling\Program.cs:line 41 
    at GenericExceptionHandling.Program.CallExternalFunction(Action funct) in c:\ 
users\siebiers\documents\visual studio 2015\Projects\GenericExceptionHandling\Ge 
nericExceptionHandling\Program.cs:line 26 
0

提供了一个通用的异常处理函数

static void Main(string[] args) 
     { 
      try 
      { 
       CallOtherLibrary(); 
      } 
      catch (Exception ex) 
      { 
       HandleException(ex); 
      } 
     } 


     private static void HandleException(Exception ex) 
     { 
      if (ex is ExceptionA) 
      { 
       ProcessErrorA(); 
      } 
      else if (ex is ExceptionB) 
      { 
       ProcessErrorB(); 
      } 
     }