2016-09-28 53 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(); 
      } 
     }