DataAnnotations CustomValidator с универсальным типом - PullRequest
1 голос
/ 12 июля 2011

Это проект MVC 3, использующий архитектуру S # arp.

В моем домене есть несколько объектов, которые наследуют NamedEntity, который является абстрактным классом, расширяющим Entity и определяющим свойство string Name.

Все эти объекты разделяют тот факт, что они должны быть уникальными именами по своему типу объекта.

Учитывая, что наборы этих объектов будут относительно небольшими (200 будет крайним случаем), я полагаю,не возражайте против поездки в базу данных, чтобы проверить, есть ли дубликат.

Мой вопрос: Каков наилучший способ легко проверить это, сохраняя при этом DRY?

Я прошел полдюжины итераций, не особо любя ни одну из них.Я попытался создать атрибут [ValidUniqueName] в ViewModel, и ViewModel можно набрать EditViewModel<T> where T: NamedEntity.Проблема заключается в том, что атрибут не знает правильный объект хранилища / задач, с которым нужно общаться из-за Generic.

Чтобы обойти это, я попытался создать ссылку INamedEntityTasks<T> во ViewModel и получить к ней доступ из ValidationContext для атрибута ValidUniqueName.Это не работает, как ожидалось, потому что Атрибут не является общим (это не может быть), и поэтому он не знает, как правильно преобразовать ValidationContext.ObjectInstance обратно во что-то пригодное для использования.

На этомТочка, единственное, что я могу придумать, это создать отдельные атрибуты [ValidUniqueFoo] [ValidUniqueBar] и т. д., что кажется плохим.В качестве альтернативы, я могу поставить проверку в каждом контроллере, но это одинаково плохо, кажется.

Ответы [ 2 ]

0 голосов
/ 12 июля 2011

На данный момент, похоже, что это будет включать в себя грязные хаки или какой-то серьезно сложный код (см. Другой ответ).Нет ничего страшного в том, чтобы писать

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 голосов
/ 12 июля 2011

Не могли бы вы просто добавить перегруженный конструктор в [ValidUniqueName]?Или я полностью упустил суть?

РЕДАКТИРОВАТЬ

Не могли бы вы передать два типа параметров в ViewModel что-то вроде

ViewModel<T, TRepository>
...