Я не согласен.
С одной стороны, некоторые из атрибутов, которые вы будете использовать для указания способа отображения свойства сущности на веб-странице, берутся из пространства имен System.Web, а не из пространства имен System.ComponentModel.DataAnnotations. Помещая эти атрибуты в свойства вашей доменной модели, ваша доменная модель зависит от System.Web. Например, есть атрибут [HiddenInput], который указывает MVC3 визуализировать поле как input type = "hidden". Это не в System.CompoenentModel.DataAnnotations.
Во-вторых, я не думаю, что вам нужны атрибуты аннотации данных в свойствах вашей сущности, чтобы иметь богатую модель домена. Богатая модель предметной области происходит от классов, которые обертывают знания в контекст. Клиентское приложение не должно знать что-либо о домене, чтобы использовать его. Вы получаете богатую модель предметной области с классами, методами и свойствами, которые описывают знания, используя вездесущий язык. Атрибуты DataAnnotations плохо подходят для вездесущего языка imo. И ваш домен - это больше, чем просто ваша сущность. Существуют фабрики, сервисы и другие шаблоны, которые вы можете использовать для построения богатой доменной модели. Домен только с сущностями и метаданными звучит для меня анемично.
В-третьих, у вас может быть сущность, которая должна отображаться на вашем веб-сайте различными способами. Когда кто-то ищет автомобиль, вы можете отобразить только марку, модель, год и миниатюру. Когда кто-то нажимает на результат поиска, вы можете отобразить несколько фотографий, обзоров и т. Д. Если бы вы использовали атрибут UIHint для объекта, чтобы сообщить веб-интерфейсу, как визуализировать автомобиль, вы не сможете получить разные стратегии рендеринга автомобиля в разных контекстах.
Наконец, да, automapper действительно отлично подходит для DTO-преобразования ваших сущностей в модели представления. По сути, он позволяет вам заполнять копии объекта, отсоединенного от домена, для конкретных задач пользовательского интерфейса. Здесь можно безопасно использовать атрибуты HiddenInput и UIHint, чтобы сообщить MVC3, как визуализировать данные.
Ответ на комментарий 1
Что касается UIHint, я упомянул об этом здесь, потому что он имеет особое значение для MVC3 EditorTemplates. В случаях, когда частичное представление предполагает получение входных данных, какова структура представления? Текстовые поля, раскрывающиеся списки и входные элементы, которые часто соответствуют объектам и их свойствам в некотором совокупном корне. Поэтому вам потребуется некоторое представление сущностей для инкапсуляции данных. Ваш DTO также может быть совокупным корнем с глубиной. Вы можете иметь корневой DTO со скалярными свойствами (текст / дата / bool), свойствами навигации (раскрывающийся список) и свойствами коллекции (ul / ol / table).
Мы создаем соответствующие модели представления для многих объектов в сводном корне и реализуем их как представления с использованием EditorTemplates. Если мы когда-нибудь захотим переключиться на другой EditorTemplate, мы можем применить UIHint к свойству viewmodel. Таким образом, мы можем сказать ему, чтобы "визуализировать местоположение как карту Google". Automapper может сопоставить навигационные свойства и свойства коллекции с соответствующими моделями представления, формируя настолько сложное представление сущностей вашего домена, сколько вам нужно для пользователя.
Простите, если я неправильно понимаю, что вы подразумеваете под плоским dto.
Ответ на комментарий 2
Viewmodel dto может сгладить / денормализовать некоторые свойства (используя automapper), если ваши требования требуют этого. Например, рассмотрим университетский объект. У него может быть много имен на многих языках (переводы), что намекает на сущность UniversityName в совокупности, а университет имеет коллекцию имен (1..n). Из этих имен 1 может представлять собой OfficialName / NativeName, а другое может представлять TranslatedName для CurrentUICulture пользователя. Другие сущности в коллекции могут представлять TranslatedNames, которые пользователь не понимает, и их не нужно беспокоить.
Если у вас есть представление, которое интересуется только этими 2 именами в коллекции, вы можете преобразовать их в первоклассные свойства в модели представления:
public class UniversityViewModel
{
public string OfficialName { get; set; }
public string TranslatedName { get; set; }
// ...other properties
}
Это случай, когда денормализованная частьсущность при преобразовании в модель представления dto может иметь смысл.Обратите внимание, что модель представления является анемичной - пустой контейнер для передачи данных из контроллера в представление.Это прекрасно, и на самом деле, это поощряется.
Ответ на оригинальный вопрос
Чтобы ответить на исходный вопрос, полезно подумать о модели вашего домена и объектахв качестве слоя - более конкретно, нижний слой .Многоуровневое программное обеспечение легче понять, если вы считаете, что различные проблемы в приложении зависят от других проблем.MVC3 - это уровень представления / пользовательского интерфейса, который будет зависеть от уровней, расположенных под ним - один из тех, которые являются уровнем вашего домена.
Если вы хотите получить доступ к файлу ресурса в пользовательском интерфейсе из уровня домена, вы идете в противоположном направлении.Вы сделаете низкий уровень зависимым от более высокого уровня.Если библиотека вашего домена зависит от библиотеки UI для ресурса, а библиотека UI зависит от домена для сущностей, вы в итоге получаете циклическую зависимость.Я думаю, что вы могли бы сделать это, используя рефлексию, если вам нужно, но в этом случае вы будете бороться с рамками.MVC и .NET в целом могут быть не лучшим выбором для вас, если это так.
Я на самом деле считаю файлы ресурсов сквозной задачей.Наше приложение покрыто i18n, и часто мы обнаруживаем, что нам нужны одни и те же языковые текстовые ресурсы как в домене, так и в интерфейсе пользователя.
Нет ничего плохого в том, чтобы поместить атрибут Display в сущность.Но если вы хотите использовать ресурсы для него, то либо поместите этот ресурс на уровень домена, либо, если вы считаете, что он там не принадлежит, на более низкий уровень.Таким образом, к нему могут получить доступ как домен, так и пользовательский интерфейс.