Отображение атрибутов проверки от доменного объекта до DTO

У меня есть стандартный Доменный объект Слоя:

public class Product
{
    public int Id { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set;}
}

которому применили некоторые атрибуты проверки:

public class Product
{
    public int Id { get; set; }

    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    public string Name { get; set; }

    [NotLessThan0]
    public decimal Price { get; set;}
}

Как Вы видите, я составил эти атрибуты полностью. Какая платформа проверки (Блок проверки допустимости NHibernate, DataAnnotations, ValidationApplicationBlock, замок Validator, и т.д.) используемый здесь не важна.

В моем клиентском слое у меня также есть стандартная установка, где я не использую сами Доменные объекты, но вместо этого отображаю их на ViewModels (иначе DTO), который использует мой слой представления:

public class ProductViewModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set;}
}

Давайте затем скажем, что я хочу, чтобы мой клиент/представление был в состоянии выполнить некоторые основные проверки уровня свойства.

Единственным путем я вижу, что могу сделать, это должно повторить определения проверки в объекте ViewModel:

public class ProductViewModel
{
    public int Id { get; set; }

    // validation attributes copied from Domain entity
    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    public string Name { get; set; }

    // validation attributes copied from Domain entity
    [NotLessThan0]
    public decimal Price { get; set;}
}

Это ясно не удовлетворительно, поскольку я теперь повторил бизнес-логику (проверка уровня свойства) в уровне ViewModel (DTO).

Таким образом, что может быть сделано?

При предположении, что я использую средство автоматизации как AutoMapper для отображения моих Доменных объектов на мой ViewModel DTOs, также не было бы здорово так или иначе передать логику проверки для отображенных свойств в ViewModel также?

Вопросы:

1) Действительно ли это - хорошая идея?

2) Если так, это может быть сделано? В противном случае, каковы альтернативы, если таковые имеются?

Заранее спасибо за любой вход!

32
задан Martin Suchanek 15 January 2010 в 22:53
поделиться

7 ответов

< b > и < strong > не обязательно одинаковы. < strong > , как вы предлагали, для более высокого акцента, в то время как < b > предназначены только для стиля. Так что не стоит менять их вслепую.

Некоторые люди скажут, что тег < b > устаревает, но он еще жив и бьет ногами . Однако; это не очень смысловый, как вы говорите, так что, возможно, лучше использовать < span > и стиль.

-121--1133201-

Java имеет отличную поддержку форматирования чисел в тексте в разных языковых стандартах с классом NumberFormat :

С текущим языковым стандартом

NumberFormat.getNumberInstance().format(5000000);

вы получите (со шведским языковым стандартом) последовательность: 5 000 000

... или с конкретным языковым стандартом (например, французский, который также приводит к 5 000 000 ):

NumberFormat.getNumberInstance(Locale.FRANCE).format(5000000);
-121--2749527-

Если используется что-то, поддерживающее DataAnnotations, можно использовать класс метаданных, содержащий атрибуты проверки:

public class ProductMetadata 
{
    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    public string Name { get; set; }

    [NotLessThan0]
    public decimal Price { get; set;}
}

и добавьте его в атрибут MetadityTypeAttribute в сущности домена & DTO:

[MetadataType(typeof(ProductMetadata))]
public class Product

и

[MetadataType(typeof(ProductMetadata))]
public class ProductViewModel

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

11
ответ дан 27 November 2019 в 21:12
поделиться

Почему бы не использовать интерфейс для выражения вашего намерения? Например:

public interface IProductValidationAttributes {
    [NotEmpty, NotShorterThan10Characters, NotLongerThan100Characters]
    string Name { get; set; }

    [NotLessThan0]
    decimal Price { get; set;}
}
3
ответ дан 27 November 2019 в 21:12
поделиться

Прежде всего, нет понятия «стандартного» объекта домена. Для меня стандартная доменная сущность не имеет никаких затурсов для начала. Если вы берете этот подход, вы можете иметь более значимые API, на самом деле что-то передает о вашем домене. Итак, вы можете получить прикладную службу, которая обрабатывает ваш DTO, создает команды, которые вы можете выполнить непосредственно против вас доменные объекты, такие как SetContactInfo, ChangePrice и т. Д. Каждый из них может повысить ValidationException, который, в свою очередь, вы можете собрать в вашем обслуживании и представлять Пользователь. Вы все еще можете оставить свои атрибуты в свойствах DTO для простой проверки уровня атрибута / имущества. Для чего-либо еще консультируйтесь с вашим доменом. И даже если это Crud Application, я бы не подвергался воздействию своих доменных объектов на презентационный слой.

0
ответ дан 27 November 2019 в 21:12
поделиться

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

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

Короче говоря, поместите атрибуты проверки данных в свои модели представления и оставьте их вне моделей предметной области.

9
ответ дан 27 November 2019 в 21:12
поделиться

Если вы используете рукописные сущности домена, почему бы не поместить сущности домена в их собственную сборку и не использовать ту же сборку как на клиенте, так и на сервере. Вы можете повторно использовать одни и те же проверки.

1
ответ дан 27 November 2019 в 21:12
поделиться

Я тоже некоторое время обдумывал это. Я полностью понимаю ответ Брэда. Однако предположим, что я хочу использовать другую структуру проверки, которая подходит для аннотирования как сущностей предметной области, так и моделей представления.

Единственное решение, которое я могу придумать на бумаге, которое все еще работает с атрибутами, - это создать другой атрибут, который «указывает» на свойство сущности предметной области, которое вы зеркалируете в своей модели представления. Вот пример:

// In UI as a view model.
public class UserRegistration {
  [ValidationDependency<Person>(x => x.FirstName)]
  public string FirstName { get; set; }

  [ValidationDependency<Person>(x => x.LastName)]
  public string LastName { get; set; }

  [ValidationDependency<Membership>(x => x.Username)]
  public string Username { get; set; }

  [ValidationDependency<Membership>(x => x.Password)]
  public string Password { get; set; }
}

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

Есть какие-нибудь мысли?

1
ответ дан 27 November 2019 в 21:12
поделиться

Оказывается, AutoMapper может сделать это для нас автоматически, что является лучшим сценарием.

AutoMapper-users: Перенести атрибуты валидации во вью-модель?
http://groups.google.com/group/automapper-users/browse_thread/thread/efa1d551e498311c/db4e7f6c93a77302?lnk=gst&q=validation#db4e7f6c93a77302

Я еще не успел опробовать предложенные там решения, но собираюсь сделать это в ближайшее время.

4
ответ дан 27 November 2019 в 21:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: