Diese Frage wurde von meinen Kämpfen mit ASP.NET MVC inspiriert, aber ich denke, es gilt auch für andere Situationen.Wie "C# Attribute" in Models und ViewModels "DRY-up"?
Lassen Sie uns sagen, ich habe ein ORM-generierte Modell und zwei Viewmodels (eine für eine Ansicht "Details" und eine für ein "Bearbeiten" -Ansicht):
Modell
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; }
}
Anzeige Ansichtsmodell
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; }
}
bearbeiten Ansichtsmodell
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; }
}
Beachten Sie, dass die Attribute auf den Viewmodels sind nicht DRY - eine Menge an Informationen wird wiederholt. Stellen Sie sich nun vor, dass dieses Szenario mit 10 oder 100 multipliziert wird, und Sie können sehen, dass es schnell ziemlich mühsam und fehleranfällig werden kann, die Konsistenz zwischen ViewModels (und damit zwischen den Views) zu gewährleisten.
Wie kann ich diesen Code "DRY-up"?
Bevor Sie antworten, "setzen Sie einfach alle Attribute auf FooModel
," Ich habe das versucht, aber es hat nicht funktioniert, weil ich meine ViewModels "flach" halten muss. Mit anderen Worten, ich kann nicht jedes ViewModel mit einem Model zusammenstellen - ich brauche mein ViewModel, um nur die Eigenschaften (und Attribute) zu haben, die von der View konsumiert werden sollen, und die View kann nicht in Untereigenschaften einbetten Auf die Werte kommen.
aktualisieren
Antwort LukLed lässt darauf schließen Vererbung. Dies reduziert definitiv die Menge an nicht-DRY-Code, aber es beseitigt es nicht. Beachten Sie, dass in meinem obigen Beispiel das DisplayName
-Attribut für die Eigenschaft Category
zweimal geschrieben werden muss, da der Datentyp der Eigenschaft zwischen den Anzeige- und Bearbeitungsansichtsmodellen unterschiedlich ist. Dies wird im kleinen Maßstab keine große Sache sein, aber wenn die Größe und Komplexität eines Projekts größer wird (man stelle sich viel mehr Eigenschaften, mehr Attribute pro Eigenschaft, mehr Ansichten pro Modell vor), gibt es immer noch das potentiell "Sich selbst wiederholen" eine angemessene Menge. Vielleicht nehme ich DRY hier zu weit, aber ich würde immer noch lieber alle meine "freundlichen Namen", Datentypen, Validierungsregeln usw. nur einmal eingeben.
Danke, jfar und +1. Ja, genau, ich versuche, DisplayFor() und EditorFor() zu verwenden (obwohl ich selbst in Fällen, in denen ich das nicht kann, meine ViewModels immer noch DRY). Ihre Idee würde viele Attribute überflüssig machen, was eine große Hilfe ist. Ich frage mich allerdings, ob ich auch eine benutzerdefinierte Eigenschaft (und ein paralleles benutzerdefiniertes Attribut) hinzufügen könnte, die angeben würde, ob eine bestimmte Eigenschaft für ein bestimmtes ViewModel gerastert werden soll. Dies würde mir erlauben, ein ViewModel zu haben, das alle Ansichten behandelt, was bedeutet, dass ich nie oder fast nie Attribute wiederholen müsste. – devuxer
Nun, die einzige Einschränkung sind die Standardeigenschaften von ModelMetadata. Wenn Sie weitere Informationen hinzufügen und ein MyModelMetadata erstellen müssen: ModelMetatdata, müssen Sie auch ein eigenes benutzerdefiniertes ViewPage mit einer benutzerdefinierten MyModelMetadata-Eigenschaft erstellen ODER das ViewData.ModelMetadata in beliebige ASPX- oder ASCX-Dateien umwandeln, die Sie verwenden. – jfar