我有一個專有的C#庫,它基本上是對一些C 代碼的包裝。 它所提供的功能看起來像這樣:
public int func(in params, out params. ...)
回傳的int表示成功(0),一些錯誤代碼(<0)或一些資料(>0,例如成功讀取的位元組數)。
此外,該庫提供了一個public EnumErrorCode GetLastError()函式
我的任務是撰寫另一個包裝器,將每個帶有錯誤代碼的函式轉換為拋出例外的函式
。雖然很容易把returncode放到例外中去
public class MyException : Exception
{
public int RetVal { get; }
public MyException(int retVal) :/span> { RetVal = retVal;}
public MyException(string message, int retVal) : base(message) { RetVal = retVal; }
}
使用起來像
public void func(int a)
{
var retVal = api.func(a);
switch (retVal)
{
case 0: return;
case 1: throw new MyException("same error across all funcs"/span>, retVal)。
case 2: throw new MyException("func specific error"/span>, retVal)。
default: throw new MyException(retVal)。
}
我很難找出正確的方法將EnumErrorCode GetLastError()也加入到例外中。
首先,我應該引入一個新的屬性public EnumErrorCode ErrorCode { get; },EnumErrorCode定義在C#專有庫中,還是應該直接存盤一個int?
其次,在拋出例外的同時呼叫GetLastError()是否可以呢?
case 1: throw new MyException("Mayhem!", retVal, GetLastError() )。)
在拋出時再次呼叫國外的未知代碼似乎并不正確。還有什么其他的可能性?
感謝Fildor的詳細解答。 我想我會在函式中混入特定的資訊(由API檔案提供),并在Create函式中使用一個字典作為EnumErrorCode的映射
。public interface IMyExceptionFactory
{
MyException Create(string funcSpecificCodeMsg, int returnCode, int errorCode) 。
}
//snip; }
int returnCode = CallToThirdParty();
if (returnCode < 0)
{
int errorCode = -1;
try; try
{
errorCode = (int)GetLastError()。
}
catch (Exception) { }
switch (returnCode)
{
case -1: throw _exceptionFactory.Create("invalid handle"/span>, returnCode, errorCode)。
case 2: throw _exceptionFactory.Create("func specific error -2"/span>, returnCode, errorCode)。
...
default: throw _exceptionFactory.Create("Unknown returnCode", returnCode, errorCode) 。
}
uj5u.com熱心網友回復:
首先。重申評論中的觀點:
GetLastError與另一個try/catch結合起來。
使用第三方列舉
這取決于你想從你的配接器的客戶端隱藏第三方的程度。 如果他們不應該知道(至少在使用你的配接器時,當然,他們可能會知道有一個第三方)第三方,那么你將需要隱藏原始列舉。這可以通過制作您自己的 Enum 的 "副本 "來實作。這是有可能的,但它有嚴重的隱患。在第三方的每次更新中,你都需要檢查該列舉是否發生了變化,并相應地改變你的代碼。這可能會導致破壞性變化,甚至。
我過去所做的只是使用并公開了整數值,并提供了一個ErrorCodeToString函式,該函式基本上是將int轉換為第三方列舉,然后做一個ToString。這對于我的目的來說已經足夠了,當然我并不聲稱這是the甚至是a"最佳實踐"。
創建例外情況
回顧一下我們所擁有的:- 函式的回傳代碼為
- 0 == "ok"
- >0(只有一些)==一些整數值的結果。
- <0 ,其中...
- '-1'是所有函式共有的錯誤
- '-1'是所有函式共有的錯誤。
- '-2'和更小的是特定函式的錯誤(每個函式的含義不同)
GetLastError來檢索errorCode(=>列舉)。
現在,有一個問題會是。除了擁有ErrorCodeEnum值之外,維護一個所有特定函式returncodes的詳盡表格是否有益?
如果是的話:事情就變得有點復雜了。但也許我們可以把這個問題放在一邊暫時,而把注意力放在 Enum 值上。
當然,你不會想為每一個函式都寫一個自定義處理。因此,你所需要的是某種例外工廠。
我對此的假設是:
我的假設是
- 你可能想分配給每個函式一個自定義的處理方法。
- 你可能想給每個列舉值分配一個不同的例外訊息。
- 你已經展示了一個自定義的
MyException型別,所以你可能想使用它。
現在,你需要做出一個設計決定。你可以使用一個例外型別,并讓它擁有屬性。或者你可以從你的基本例外型別中派生出 "子 "型別。
后者將方便你將你想要/需要處理的例外與你(或客戶)想要 "冒出 "的其他例外進行分組或單獨處理。
無論如何,你都希望有一個類似于
的介面。public interface IMyExceptionFactory
{
MyException Create(int returnCode, int errorCode) /span>。
在你的配接器中使用(我猜你會想要注入它),這樣它就可以施展它的魔法,而你可以拋出它給你的任何東西。
例如:
// snip
int returnCode = CallToThirdParty();
if( returnCode < 0 )
{
int errorCode = GetLastError();
throw _exceptionFactory.Create(returnCode, errorCode);
在它的實作中,你將建立適當的Exception,并將Message(也許是派生型別)和其他屬性設定為正確的值。
例如,你可以建立一個字典,讓你通過 errorCodes 等來查找訊息。然后你可以決定是通過硬編碼還是通過配置來構建這個字典。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/320033.html
標籤:
