Я собираюсь выбросить это там, если вам нужно высмеивать ваши модели, вы делаете это неправильно. Ваши модели должны быть тупыми имущественными сумками.
Нет абсолютно никаких причин, по которым ваша модель должна иметь метод SendEmail. Это функциональность, которая должна вызываться из контроллера, вызывающего службу EmailService.
Отвечая на ваш вопрос:
После многих лет работы с шаблонами Разделения Концернов (SOC), такими как MVC, MVP, MVVM и просмотром статей от людей, которые меня ярче (хотелось бы найти тот, о котором я подумаю, но, возможно, я прочитал его в журнал). В конечном итоге в корпоративном приложении вы получите 3 различных набора объектов модели.
Раньше я очень любил заниматься проектированием, управляемым доменом (DDD), используя один набор бизнес-объектов, которые представляли собой как простые старые объекты c # (POCO), так и Persistent Ignorant (PI). Наличие моделей доменов, которые являются POCO / PI, оставляет вас с чистого листа объектов, где нет кода, связанного с доступом к хранилищу объектов, или имеющих другие атрибуты, которые имеют схематическое значение только для 1 области кода.
Хотя это работает и может работать довольно хорошо в течение определенного периода времени, в конечном итоге возникает переломный момент, когда сложность выражения взаимосвязи между представлением, моделью предметной области и физической моделью хранения становится слишком сложной для правильного выражения с 1 набором. юридических лиц.
Чтобы устранить несоответствия импеданса View, Domain и Storage, вам действительно нужны 3 набора моделей. Ваши ViewModels будут точно соответствовать привязке ваших представлений, чтобы облегчить работу с пользовательским интерфейсом. Так что это часто имеет такие вещи, как добавление списка для заполнения раскрывающихся списков значениями, которые действительны для вашего вида / действия редактирования.
Посередине находятся доменные объекты, это те объекты, которые вы должны проверить в соответствии с вашими бизнес-правилами. Таким образом, вы будете отображать в / из них с обеих сторон в / из вида и в / из слоя хранения. В этих объектах вы можете прикрепить свой код для проверки. Лично я не фанат использования атрибутов и привязки логики валидации к вашим доменным объектам. Имеет смысл объединить атрибуты проверки с вашими ViewModels, чтобы воспользоваться преимуществами встроенной функциональности проверки на стороне клиента MVC.
Для проверки я бы порекомендовал использовать такую библиотеку, как FluentValidation (или вашу собственную, которую нетрудно написать), которая позволяет вам отделить ваши бизнес-правила от ваших объектов. Несмотря на то, что благодаря новым функциям MVC3 вы можете выполнять удаленную проверку с обратной стороны и отображать ее на стороне клиента, эта опция позволяет обрабатывать настоящую бизнес-проверку.
Наконец-то у вас есть модели хранения. Как я уже говорил ранее, я очень усердствовал о возможности повторного использования объектов PI через все слои, поэтому в зависимости от того, как вы настраиваете долговременное хранилище, вы можете напрямую использовать ваши доменные объекты. Но если вы воспользуетесь такими инструментами, как Linq2Sql, EntityFramework (EF) и т. Д., У вас, скорее всего, будут автоматически сгенерированные модели с кодом для взаимодействия с поставщиком данных, поэтому вы захотите сопоставить свои доменные объекты с вашими персистентными объектами.
Итак, заверните все это, это будет стандартный логический поток в действиях MVC
Пользователь переходит на страницу редактирования товара
EF запрашивает базу данных, чтобы получить информацию о существующем продукте, на уровне хранилища объекты данных EF отображаются на бизнес-объекты (BE), поэтому все методы уровня данных возвращают BE и не имеют внешней связи с EF объекты данных. (Таким образом, если вы когда-либо меняете поставщика данных, вам не нужно изменять ни одной строки кода, за исключением внутренней реализации)
Контроллер получает Product BE и сопоставляет его с Product ViewModel (VM) и добавляет коллекции для различных параметров, которые можно установить для раскрывающихся списков
Вернуться в представление (theview, ProductVM)
Пользователь редактирует продукт и отправляет форму
Проверка на стороне клиента пройдена (полезно для проверки даты / проверки номера вместо того, чтобы отправлять форму для обратной связи)
ProductVM сопоставляется с ProductBE, и в этот момент вы проверяете бизнес-правила по линиям ValidationFactory.Validate(ProductBE)
, если недействительные возвращаемые сообщения для просмотра и отмены редактирования, в противном случае продолжайте
Вы передаете ProductBE в свою модель хранилища, во внутренней реализации слоя данных сопоставляете ProductBE с объектом данных продукта для EF и обновляете базу данных.
2016 edit: удалено использование Interface
, поскольку разделение интересов и интерфейсов полностью ортогональны.