我一次又一次地回想起對需要訪問某些上下文(例如NH中的ISession,例如IRepository)的POCO對象執行驗證的最佳方式。Validation without ServiceLocator
我仍然能看到的唯一選擇是使用服務定位,所以我的驗證看起來像:
public User : ICanValidate {
public User() {} // We need this constructor (so no context known)
public virtual string Username { get; set; }
public IEnumerable<ValidationError> Validate() {
if (ServiceLocator.GetService<IUserRepository>().FindUserByUsername(Username) != null)
yield return new ValidationError("Username", "User already exists.")
}
}
我已經使用反轉控制和依賴注入和真的不喜歡由於一些事實ServiceLocator:
- 難以維持隱式依賴。
- 難以測試代碼。
- 潛在的線程問題。
- 僅顯式依賴於ServiceLocator。
- 代碼變得更難理解。
- 需要在測試期間註冊ServiceLocator接口。
但是另一方面,對於普通的POCO對象,我沒有看到任何其他的方式來執行上面沒有ServiceLocator並僅使用IoC/DI的驗證。
目前,我在服務層中執行此類驗證。因此,無論何時一個演員試圖更改用戶名(當然可能有些不同),該服務會執行此驗證。一個明顯的缺點是每個使用用戶的服務都必須執行此檢查(即使它是一次調用)。
所以問題是:是否有任何方式使用DI/IoC的上述情況?
謝謝,
德米特里。
我完全同意這一點。目前,我在服務層執行'Unique'驗證,但是我必須複製/繼承與用戶一起工作的每個服務中的邏輯。 – 2010-05-11 00:02:06
@Dmitriy:這很好,可以理解;然後,我將這個邏輯放在客戶端/用戶交互的*服務*中,而不是特定的項目。如果您需要保持服務整潔,請委派專門的驗證人。 – Aaronaught 2010-05-11 00:29:20
我所有的'服務'目前都是特定用例/故事的實現(所以它們可以被看作是用戶交互的)。 我會做的是可能添加另一個依賴項'IUserValidation'並將其注入到Use-Case服務中。我認爲這將是現在最好的方式。 – 2010-05-11 01:55:27