Câu hỏi này được lấy cảm hứng từ cuộc đấu tranh của tôi với ASP.NET MVC, nhưng tôi nghĩ nó cũng áp dụng cho các tình huống khác.Làm thế nào để "DRY up" C# thuộc tính trong mô hình và ViewModels?
Hãy nói rằng tôi có một mô hình ORM tạo và hai ViewModels (một cho một "chi tiết" cái nhìn và một cho một "chỉnh sửa" quan điểm):
Mẫu
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; }
}
Display 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; }
}
Sửa 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; }
}
Lưu ý rằng các thuộc tính trên Chế độ xem không phải là DRY - nhiều thông tin được lặp lại. Bây giờ hãy tưởng tượng kịch bản này nhân với 10 hoặc 100, và bạn có thể thấy rằng nó có thể nhanh chóng trở nên khá tẻ nhạt và dễ bị lỗi để đảm bảo tính nhất quán trên ViewModels (và do đó trên các Views).
Tôi làm cách nào để "TẮT" mã này?
Trước khi bạn trả lời, "Chỉ cần đặt tất cả các thuộc tính trên FooModel
", tôi đã thử điều đó, nhưng nó không hoạt động vì tôi cần giữ cho ViewModels "phẳng". Nói cách khác, tôi không thể chỉ soạn mỗi ViewModel với một Model - tôi cần ViewModel của mình chỉ có các thuộc tính (và các thuộc tính) cần được View sử dụng, và View không thể burrow vào các thuộc tính con nhận được các giá trị.
Cập nhật
LukLed của câu trả lời gợi ý sử dụng thừa kế. Điều này chắc chắn làm giảm số lượng mã không DRY, nhưng nó không loại bỏ nó. Lưu ý rằng, trong ví dụ của tôi ở trên, thuộc tính DisplayName
cho thuộc tính Category
cần phải được viết hai lần vì loại dữ liệu của thuộc tính khác nhau giữa Chế độ xem hiển thị và chỉnh sửa. Đây sẽ không phải là một vấn đề lớn trên quy mô nhỏ, nhưng khi kích thước và độ phức tạp của một dự án tăng lên (hãy tưởng tượng nhiều thuộc tính hơn, nhiều thuộc tính hơn cho mỗi thuộc tính, nhiều lượt xem hơn cho mỗi mô hình), vẫn có khả năng "lặp lại chính mình" một số tiền hợp lý. Có lẽ tôi đang dùng DRY quá xa ở đây, nhưng tôi vẫn muốn có tất cả "tên thân thiện", kiểu dữ liệu, quy tắc xác thực, v.v. chỉ được gõ một lần.
Cảm ơn, jfar và +1. Có, chính xác, tôi đang cố gắng sử dụng DisplayFor() và EditorFor() (mặc dù, ngay cả trong trường hợp tôi không thể, tôi vẫn muốn DRY lên ViewModels của tôi). Ý tưởng của bạn sẽ loại bỏ rất nhiều nhu cầu cho các thuộc tính, đó là một trợ giúp tuyệt vời. Tôi tự hỏi, mặc dù, nếu tôi cũng có thể thêm một tài sản tùy chỉnh (và một thuộc tính tùy chỉnh song song) mà sẽ cho biết liệu để giàn giáo một tài sản cụ thể cho một ViewModel cụ thể. Điều này sẽ cho phép tôi có một ViewModel xử lý tất cả các khung nhìn, có nghĩa là tôi sẽ không bao giờ hoặc gần như không bao giờ cần phải lặp lại các thuộc tính. – devuxer
Giới hạn duy nhất là các thuộc tính mặc định của ModelMetadata. Nếu bạn cần thêm thông tin và tạo MyModelMetadata: ModelMetatdata, bạn cũng sẽ tạo ViewPage tùy chỉnh của riêng mình với thuộc tính MyModelMetadata tùy chỉnh HOẶC truyền ViewData.ModelMetadata bên trong bất kỳ tệp .aspx hoặc .ascx nào bạn đang sử dụng. – jfar