Этот вопрос был вдохновлен моей борьбой с ASP.NET MVC, но я думаю, что это относится и к другим ситуациям.
Скажем, у меня есть ORM-сгенерированная модель и две ViewModels (одна для "подробного" представления и одна для "редактирования" ):
Model
public class FooModel // ORM generated
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public int Age { get; set; }
public int CategoryId { get; set; }
}
Показать ViewModel
public class FooDisplayViewModel // use for "details" view
{
[DisplayName("ID Number")]
public int Id { get; set; }
[DisplayName("First Name")]
public string FirstName { get; set; }
[DisplayName("Last Name")]
public string LastName { get; set; }
[DisplayName("Email Address")]
[DataType("EmailAddress")]
public string EmailAddress { get; set; }
public int Age { get; set; }
[DisplayName("Category")]
public string CategoryName { get; set; }
}
Изменить ViewModel
public class FooEditViewModel // use for "edit" view
{
[DisplayName("First Name")] // not DRY
public string FirstName { get; set; }
[DisplayName("Last Name")] // not DRY
public string LastName { get; set; }
[DisplayName("Email Address")] // not DRY
[DataType("EmailAddress")] // not DRY
public string EmailAddress { get; set; }
public int Age { get; set; }
[DisplayName("Category")] // not DRY
public SelectList Categories { get; set; }
}
Обратите внимание, что атрибуты в ViewModels не являются DRY - много информации повторяется. Теперь представьте, что этот сценарий умножен на 10 или 100, и вы можете видеть, что он может быстро стать довольно утомительным и подверженным ошибкам, чтобы обеспечить согласованность между ViewModels (и, следовательно, в представлениях).
Как я могу "сушить" этот код?
Прежде чем ответить: "Просто поместите все атрибуты на FooModel
", я пробовал это, но это не сработало, потому что мне нужно, чтобы мои ViewModels "плоские". Другими словами, я не могу просто составить каждый ViewModel с помощью модели - мне нужно, чтобы моя ViewModel имела только свойства (и атрибуты), которые должны быть использованы View, и View не может зарываться в под-свойства для получить значения.
Обновление
Ответ LukLed предполагает использование наследования. Это определенно уменьшает количество кода, отличного от DRY, но не устраняет его. Обратите внимание, что в моем примере выше атрибут DisplayName
для свойства Category
должен быть записан дважды, потому что тип данных свойства отличается между отображением и редактированием ViewModels. Это не будет большой проблемой в небольших масштабах, но по мере увеличения масштабов и сложности проекта (представьте себе, что больше свойств, больше атрибутов на свойство, больше просмотров на модель), по-прежнему существует потенциальная возможность для "повторять себя" достаточно. Возможно, я слишком сильно забираю DRY, но у меня все еще есть все мои "дружественные имена", типы данных, правила проверки и т.д., Которые были напечатаны только один раз.