Пользовательский атрибут DataAnnotation с доступом к хранилищу данных в ASP.NET MVC 2 - PullRequest
2 голосов
/ 05 апреля 2010

У меня есть приложение, разработанное с использованием шаблона репозитория, и мой код подготовлен для необязательного внедрения зависимостей в будущем, если нам потребуется поддержка другого хранилища данных.

Я хочу создать собственный атрибут проверки для моих объектов содержимого. Этот атрибут должен выполнять поиск в хранилище данных. Например, мне нужно, чтобы в моем контенте были уникальные слагы. Чтобы проверить, существует ли Slug, я хочу использовать пользовательский атрибут DataAnnotation в моем объекте содержимого Base (вместо ручной проверки, существует ли Slug каждый раз в действиях Insert моего контроллера). Логика атрибутов сделает проверку.

До сих пор я придумал это:

public class UniqueSlugAttribute : ValidationAttribute
{
    private readonly IContentRepository _repository;

    public UniqueSlugAttribute(ContentType contentType)
    {
        _repository = new XmlContentRepository(contentType);
    }

    public override bool IsValid(object value)
    {
        if (string.IsNullOrWhiteSpace(value.ToString()))
        {
            return false;
        }

        string slug = value.ToString();
        if(_repository.IsUniqueSlug(slug))
            return true;

        return false;
    }
}

часть моего Базового класса контента:

...
        [DataMember]
        public ContentType ContentType1 { get; set; }

        [DataMember]
        [Required(ErrorMessageResourceType = typeof (Localize), ErrorMessageResourceName = "Validation_SlugIsBlank")]
        [UniqueSlug(ContentType1)]
        public string Slug
        {
            get { return _slug; }
            set
            {
                if (!string.IsNullOrEmpty(value))
                    _slug = Utility.RemoveIllegalCharacters(value);
            }
        }
...

Ошибка в строке

    [UniqueSlug(ContentType1)]

говоря: «Аргументом атрибута должно быть постоянное выражение, выражение typeof или выражение создания массива типа параметра атрибута.»

Позвольте мне объяснить, что мне нужно предоставить параметр ContentType1 классу Constructor of UniqueSlug, потому что я использую его в своем поставщике данных.

На самом деле это та же самая ошибка, которая появляется, если вы попытаетесь сделать это с помощью встроенного атрибута Required:

[Required(ErrorMessageResourceType = typeof (Localize), ErrorMessageResourceName = Resources.Localize.SlugRequired]

Это не позволяет нам устанавливать его на динамический контент. В первом случае ContentType1 становится известным во время выполнения, во втором случае Resources.Localize.SlugRequired также становится известным во время выполнения (поскольку параметры культуры назначаются во время выполнения).

Это действительно раздражает и делает невозможным множество вещей и сценариев реализации.

Итак, мой первый вопрос: как избавиться от этой ошибки? Второй вопрос, который у меня возникает, - думаете ли вы, что я должен каким-либо образом изменить код проверки?

1 Ответ

1 голос
/ 05 апреля 2010

Единственный способ избавиться от ошибки - сделать то, что она говорит, и добавить статический контент в свои атрибуты.Помните, что назначение атрибутов - для метаданных в вашем коде, которые специально предназначены для поиска информации о вашем коде во время выполнения.Создание этой динамики отрицательно сказалось бы на этой цели.

Мне кажется, что если ваш слаг является динамическим в зависимости от типа контента, то свойство Slug должно быть объектом, который инициализируется с типом контента.Исходя из опубликованного кода атрибута, нет необходимости инициализировать репозиторий в конструкторе - так что переместите его в метод IsValid() и сделайте все там, и просто сделайте небольшую проверку, чтобы убедиться, что значение приведено к Slug и что свойство ContentType установлено.

Если вам нужно выполнить кучу сценариев динамической реализации вокруг атрибутов, это может указывать на проблему проектирования.

...