簡體   English   中英

在Web API的.NET客戶端庫中管理異常

[英]Managing exceptions in a .NET client library for a web API

我正在為公共Web API構建.NET客戶端庫。 我苦苦掙扎的事情之一是如何最好地向庫用戶指示錯誤情況。 顯然,當執行失敗時,我的庫應該拋出異常或將異常傳遞給調用者,但是我應該使用現有的異常還是為我的庫創建新的異常? 如果創建新的例外,我應該只創建一個還是多個例外?

選項1:僅使用現有例外

在最基本的方面,例如,我可以throw new Exception("API authentication error."); 但這是非常通用的,之后需要大量處理才能處理。 我還可以使用更合適的現有異常,例如System.Security.Authentication.AuthenticationException ,但是由於所有不同的命名空間,使用該庫將很尷尬。 在某些情況下,沒有什么比InvalidOprationException更合適的了,因此對於使用庫處理錯誤的人來說,采用這種方法似乎很麻煩。 最簡單的方法可能就是只使用HttpException類,因為在大多數情況下,大多數錯誤情況都是HTTP狀態代碼和消息的轉換。

選項2:為每種情況創建一個例外

我還可以為每種情況創建一個例外,但是將它們全部保留在庫中。 所以我可以創建一個NotFoundExceptionAuthorizationExceptionTransactionsPendingException和其他特定的異常。

選項3:為我的客戶創建一個例外

第三種選擇是創建一個自定義異常MyApiException ,其中包含針對即將出現的各種錯誤的狀態代碼(當然還有一條相應的消息)。 因此,我可能然后throw new MyApiException(401,"Not authorized.")

在我看來,選項3是最簡單的實現方法,也是調用方法最容易處理的方法。 我已經在GitHub和Codeplex上看到了使用這些選項的API客戶端。 是否有推薦的客戶端庫方法或它們都有效?

Microsoft在MSDN上擁有一些與此有關的有價值的信息:

https://msdn.microsoft.com/en-us/library/seyhszts%28v=vs.110%29.aspx

就個人而言,我傾向於執行以下操作:

  1. 在合理的情況下使用現有的例外

    例如,基於密鑰的操作在傳遞無效密鑰時拋出KeyNotFoundException

  2. 為需要的方案創建自定義例外

  3. Either<TSuccess,TFail>類似Either<TSuccess,TFail>這樣的結果類型的異常
    1. 例如: https//gist.github.com/siliconbrain/3923828
    2. 這對於諸如迭代器塊之類的東西特別有用,在迭代器塊中可能引發異常,或者當您需要支持錯誤繼續時

現有異常

public int GetMyItem(string key)
{
   if (string.IsNullOrEmpty(key)) throw new ArgumentNullException("key");
   if (!_myDictionary.ContainsKey(key))
   {
      throw new KeyNotFoundException();
   }
   // Additional implementation left out
}

自訂例外

public class ArgumentNotOddException : ArgumentException
{
    public ArgumentNotOddException(string paramName)
        : base(@"The argument must be odd", paramName)
    {

    }
}

public class MyClass
{
    public void DoSomething(int x)
    {
        if (x%3 == 0) throw new ArgumentNotOddException("x");
    }
}

兩種類型

public class MyClass
{
    public IEnumerable<IEither<int, string>> Divide(int left, IEnumerable<int> right)
    {
        foreach (var num in right)
        {
            if (num == 0)
            {
                yield return Either.Right<int, string>("cannot divide by zero");
            }
            yield return Either.Left<int, string>(left/num);
        }
    }
}

您也可以只創建一個使用異常代碼和消息的MyAppException ,但是這樣會失去表達能力,異常代碼易於輸入錯誤(除非使用枚舉),並且MyAppExceptionNotFoundException MyAppException不同。

我最好的建議是認真考慮代碼是否應該拋出,或者返回混合結果/錯誤是否合理; 在C#中這樣做有點笨拙,但是它消除了未處理的異常的負擔,並允許您在調用代碼中更加靈活。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM