我是OOP的新手,所以我需要幫助來了解這是否是正確的方式來處理它。 我有一個3層Web項目(+ DTOs),我試圖理解這是從業務對象返回到演示層的「錯誤」的最佳方式。 特別是現在我正面臨着創建一個用戶。假設我想在網站註冊時在db中創建用戶,並且我需要告訴實際用戶用戶名或電子郵件是否已被使用(這僅僅是一個示例)。例如,ASP.NET Membership.CreateUser()方法傳遞一個MembershipCreateStatus對象byRef,因此該方法用於返回一個枚舉(它駐留在另一個命名空間中...)以傳遞嘗試的狀態,並且這個可能是DuplicateEmail,DuplicateUserName等等。來自業務層的ASP.NET自定義異常處理
我實施了另一種基於例外的方式,但我希望您對此有所意見。在創建用戶BLL管理器類我創建了一個嵌套的錯誤時拋出類和嵌套枚舉的錯誤類型是這樣的:
Public Class UserManager
Public Enum ErrorType
DatabaseError = 1
UserExists = 2
EmailExists = 3
End Enum
Public Class ManagerException
Inherits Exception
Public Property ErrorType As ErrorType
Public Property SuggestedUserName As String
Public Property SuggestedEmail As String
Public Sub New()
MyBase.New()
End Sub
Public Sub New(message As String)
MyBase.New(message)
End Sub
Public Sub New(message As String, inner As Exception)
MyBase.New(message, inner)
End Sub
End Class
Public Function CreateUserLogin(user As EvaVwUserLogin) As Guid
If user Is Nothing Then
Throw New ApplicationException("No user suppied")
End If
If String.IsNullOrWhiteSpace(user.Password) OrElse String.IsNullOrWhiteSpace(user.UserName) Then
Throw New ApplicationException("Password or username missing")
End If
If CheckDuplicateUserName() Then
Dim ex As New ManagerException("Username exists")
ex.ErrorType = ErrorType.UserExists
ex.SuggestedUserName = "this username is free"
Throw ex
End If
End Function
End Class
然後在UI層(後面的aspx代碼)我叫經理和檢查,如異常這樣的:
Dim userManager As New UserManager
Try
userManager.CreateUserLogin("test", "test")
Catch ex As UserManager.ManagerException
If ex.ErrorType = userManager.ErrorType.UserExists Then
Dim suggestedUsername = ex.SuggestedUserName
' Display error message and suggested user name
End If
End Try
這是一個正確的做法,考慮到兩者的異常,枚舉是非常具體的這個經理,所以,如果我沿着這條路走下去,每個管理者都會有其與相關枚舉嵌套ManagerException?
在此先感謝您的意見一如既往。
跟進「自定義代碼」場景由Brian和人造人好心建議(我標誌着他的回答只是因爲它是更完整的布萊恩也許其它感興趣的網友MS建議)你認爲嵌套自定義返回對象並且經理類中的相對枚舉將是一個好主意? 由於這些枚舉將與這個經理類嚴格相關(並且BLL中的每個Managar類都有他自己的),您是否認爲我仍然可以在狀態代碼通過時使用它們?
編輯:我重構了這種方式......你認爲沒關係嗎?
Public Class UserManager
Public Enum ErrorType
DatabaseError = 1
UserExists = 2
EmailExists = 3
End Enum
Public Class ErrorData
Public Property ErrorType As ErrorType
Public Property SuggestedUserName As String
Public Property SuggestedEmail As String
End Class
Public Function CreateUserLogin(username As String, password As String, ByRef errorData As ErrorData) As Guid
Dim user As New EvaVwUserLogin
user.UserName = username
user.Password = password
Return CreateUserLogin(user, errorData)
End Function
Public Function CreateUserLogin(user As EvaVwUserLogin, ByRef errorData As ErrorData) As Guid
If user Is Nothing Then
Throw New ApplicationException("No user object")
End If
If String.IsNullOrWhiteSpace(user.Password) OrElse String.IsNullOrWhiteSpace(user.UserName) Then
Throw New ApplicationException("Missing password or username")
End If
Dim hashedPassword As String
hashedPassword = Crypto.HashPassword(user.Password)
If UserExists(user) Then
errorData.ErrorType = ErrorType.UserExists
errorData.SuggestedUserName = "this username is free"
Return Nothing
End If
.....
End Function
End Class
而在表示層:
Dim userManager As New UserManager
Dim managerError As New UserManager.ErrorData
Dim userId As Guid
userId = userManager.CreateUserLogin("test", "test", managerError)
If userId = Nothing Then
If managerError.ErrorType = userManager.ErrorType.UserExists Then
Dim suggestedUserName = managerError.SuggestedUserName
' Do something with suggested user name
End If
End If
謝謝大家。我沿着「自定義例外」的路徑走,因爲我在某處讀到完全相反的東西。我讀過基於組件的場景(我猜想多層架構堅持),組件不應該返回「幻數」或代碼,而是返回異常。但我想,因爲每次都必須實例化自定義異常並檢查自定義枚舉,所以這與處理自定義返回代碼非常相似,只是更昂貴。 – Manight
我認爲你讀的是在發生異常情況時,函數不應該返回「幻數」。例如,一個函數在成功時返回0,在那裏失敗時返回-1,這在.NET中是不受歡迎的。在這種情況下,優先考慮例外。但是,如果函數是*做*某事,並且結果可能是一些*預期的事情,那麼返回代碼是適當的。 – JDB