1

這是一個使用S#arp Architecture的MVC 3項目。DataAnnotations具有通用類型的CustomValidator

我的域名有幾個對象繼承NamedEntity,這是一個抽象類,它擴展了Entity並定義了string Name屬性。

所有這些對象都有一個事實,即它們在對象類型中必須是唯一的名稱。

鑑於這些對象的集合相對較小(200將是極端情況),我不介意數據庫的往返檢查是否有重複。

我的問題是,什麼是最好的方式來輕鬆驗證這一點,同時保持乾爽?

我已經經歷了六次迭代,並不特別喜歡它們中的任何一個。我已經嘗試在ViewModel上創建[ValidUniqueName]屬性,並且可以鍵入ViewModel EditViewModel<T> where T: NamedEntity。問題在於該屬性由於Generic而不知道要與之通話的正確的存儲庫/任務對象。

爲了解決這個問題,我嘗試在ViewModel中創建一個INamedEntityTasks<T>引用,並從ValidationContext中爲ValidUniqueName屬性訪問它。這不符合預期,因爲屬性不是通用的(不能),因此它不知道如何正確地將ValidationContext.ObjectInstance轉換回可用的東西。

在這一點上,我能想到的唯一的事情是創建單獨的[ValidUniqueFoo][ValidUniqueBar]等屬性,這似乎是不好的。或者,我可以將驗證放在每個控制器中,但看起來同樣很糟糕。

回答

0

現在,好像它要涉及髒黑客或一些嚴重的複雜的代碼(見其他答案)。這不是可怕有寫

public class ValidUniqueCityAttribute : ValidationAttribute { 

public override bool IsValid(object value) 
    { 
     if (value == null || !(value is CityCreateOrEditViewModel)) return base.IsValid(value); 

     INamedEntityTasks<City> tasks = new NamedEntityTasks<City>(); 

     CityCreateOrEditViewModel vm = value as CityCreateOrEditViewModel; 
     return !tasks.CheckForDuplicateName(vm.Entity.Id, vm.Entity.Name); 
    } 
} 

對於每個NamedEntity然後,我們複製&粘貼,搜索&替換...是的,它是多餘的,但它的優勢在於它允許更大的靈活性,如果我們想以除類別之外的其他方式來驗證城市名稱(例如,查找給定狀態下所有城市的主列表,例如,儘管這是完全可人爲和可怕的做法:))。

+0

這看起來不錯,但我相信你可以做出更通用的。我需要考慮那一個。 – simonlchilds

+0

讓我知道你想出了什麼!我非常想找到更通用的解決方案。如果'tasks'沒有被正確輸入(例如,如果它被輸入爲「NamedEntity」的基礎名稱),則可能得到誤報(您有一個名爲Foo的類別,但它不會讓您創建一個名爲Foo的城市)。嘗試修改'CheckForDuplicateName'來接受'NamedEntity'對象和比較類型,但'typeof(City)'不匹配'typeof(NamedEntity)',所以這也不起作用 –

+0

我到了那裏!但是我得到了錯誤的消極信息,我會在發現更多信息後發佈更多信息。 – simonlchilds

0

您可以簡單地將重載的構造函數添加到[ValidUniqueName]?還是我完全錯過了這一點?

編輯

你能傳遞兩個類型的參數,你ViewModel

ViewModel<T, TRepository> 
+0

構造函數將作爲它的參數是什麼?所以我有 '[ValidUniqueName(...)] public class EditViewModel '...不太清楚我可以通過哪些幫助。我想我可以用'ValidUniqueName(typeof(T))'來破解它,但這絕對是一個黑客攻擊。 –

+0

是的,我明白你的觀點。我認爲在使用重載構造函數時傳遞'typeof(T)'參數將是最乾淨的解決方案,但正如您所說,這將是一個骯髒的黑客攻擊。 – simonlchilds

+0

我仍然不知道這是否會起作用。爲了調用像CheckForDuplicateName這樣的函數,我需要一個類型化的INamedEntityTasks實例。即使使用Reflection來創建一些東西(比如http://omegacoder.com/?p=38),我仍然需要知道該類型在使用之前會是什麼類型(鏈接示例中的第7行)。 –

相關問題