錯誤契約與本地化
DomainKit 以 BusinessException 表達可預期的領域或應用錯誤,並提供穩定的錯誤分類與選配錯誤碼。套件不直接決定 HTTP 狀態碼、Problem Details 格式或 UI 呈現方式,這些對映由應用層負責。
BusinessException
只傳入訊息時,錯誤分類預設為 AppErrorType.BusinessRule。
throw new BusinessException("訂單目前狀態不可取消。");
需要穩定的機器可讀契約時,同時指定分類與錯誤碼。
throw new BusinessException(
"訂單已由其他流程處理。",
AppErrorType.Conflict,
"sales-order.state-conflict"
);
AppErrorType 提供下列分類:
ValidationBusinessRuleNotFoundConflictForbidden
None 只代表沒有錯誤,不可傳給 BusinessException 的分類建構式。
應用層應以 ErrorType 決定回應類別,以 ErrorCode 作為前端分支或本地化鍵。不要依賴錯誤訊息文字判斷程式流程。
內建例外
EntityNotFoundException 保存 EntityName 與 Key,錯誤分類為 NotFound,錯誤碼為 entity.not-found。Repository 的 GetAsync 在查無資料時會拋出此例外。
ConcurrencyConflictException 表示 EF Core 樂觀鎖衝突。IUnitOfWork.SaveChangesAsync 捕捉 DbUpdateConcurrencyException 後會轉成此型別,讓應用層不必直接相依 EF Core 例外。
應用層對映
下列範例只示範分類邊界,實際回應型別由宿主決定。
int statusCode = exception.ErrorType switch {
AppErrorType.Validation => StatusCodes.Status400BadRequest,
AppErrorType.NotFound => StatusCodes.Status404NotFound,
AppErrorType.Conflict => StatusCodes.Status409Conflict,
AppErrorType.Forbidden => StatusCodes.Status403Forbidden,
_ => StatusCodes.Status422UnprocessableEntity
};
記錄日誌時保留 ErrorCode、例外型別與追蹤識別碼。回傳給使用者的文字可依 UI culture 重新解析,避免把內部例外詳細資料直接輸出至 API。
DomainKit 內建資源
BusinessException、EntityNotFoundException 與 ConcurrencyConflictException 的預設訊息由 DomainKitResources 取得,並依目前 UI culture 選擇資源。自行提供訊息的建構式會直接使用呼叫端文字。
enum 與 Enumeration 顯示名稱
EnumerationLocalizer<TEnum> 使用傳入的 IStringLocalizer 尋找顯示名稱。TEnum 可以是原生 enum,也可以是繼承 EnumerationBase<TEnum, TValue> 的 Enumeration 型別。
成員名稱的取得方式依型別分流,原生 enum 取 ToString(),Enumeration 型別以反射取 Name 屬性。兩者共用同一種資源鍵格式 {型別名稱}.{成員名稱}。
ShipmentMethod.Express
OrderStatus.Draft
OrderStatus.Confirmed
// 原生 enum
EnumerationLocalizer<ShipmentMethod> methodLocalizer = new(localizer);
string method = methodLocalizer.GetDisplayName(ShipmentMethod.Express);
// Enumeration 型別,繼承 EnumerationBase<OrderStatus, int>
EnumerationLocalizer<OrderStatus> statusLocalizer = new(localizer);
string status = statusLocalizer.GetDisplayName(OrderStatus.Confirmed);
型別標註 [Flags] 時,複合值會逐成員在地化。成員名稱含 ", " 的值先切分成各個成員,分別查找資源後再以 ", " 組回,因此資源檔只需提供個別旗標的項目。
找不到資源時回傳原始成員名稱。持久化 Enumeration 值的設定方式見持久化與模型設定,該設定僅適用於 EnumerationBase<TEnum, TValue> 衍生型別,原生 enum 的欄位對映由 EF Core 自行處理。