Was ich versucheMit MVC Ansicht LabelFor/TextFor mit Ausdruck mit unbekanntem Rückgabetyp
Ich habe einen Web-App zu erreichen, wo der Benutzer ein Verwaltungsportal hat, die verwendet werden kann, bestimmte Einstellungen zu bearbeiten. Es gibt viele bearbeitbare Einstellungen, daher möchte ich einen einzelnen Satz vererbbarer MVC-Objekte erstellen, so dass ich einfach ein Einstellungsobjekt (das nur eine Zeile in einer Tabelle ist) angeben kann und die Einstellungen anzeigen und die Suchfunktionalität anbieten die Fähigkeit, hinzufügen/entfernen von Einträgen usw.
Was ich
Ein vererbbares Controller-Objekt erstellt wurde bisher. Es arbeitet, indem es den Objekttyp (wie ein User
Objekt) nimmt und ein Array von AdminField
Objekten erstellt. Jeder repräsentiert eine Zeile in der Datenbank. Die abgeleitete Controller-Klasse geht auch Metadaten für jedes Feld als Flags, so die abgeleitete Controller-Code würde wie folgt aussehen:
public class UserController : AdminBaseController<UserViewModel, User>
{
public UserController(Context context) :
base(context, new AdminField<User>[] {
new AdminField<User>(u => u.UserId, AdminFieldFlags.Hidden | AdminFieldFlags.IsID),
new AdminField<User>(u => u.UserName, AdminFieldFlags.Searchable | AdminFieldFlags.Sortable | AdminFieldFlags.Editable | AdminFieldFlags.EditLink, "User Name"),
new AdminField<User>(u => u.Password, AdminFieldFlags.Editable),
new AdminField<User>(u => u.AccessLevel, AdminFieldFlags.Editable)
}, "User")
{
}
}
Der erste Parameter ist ein Lambda, das zeigt, wie sich aus dem Objekt das referenzierte Feld zu bekommen.
Hier ist die Methode Signatur für den AdminField
Konstruktor:
public AdminField(Expression<Func<TMaintainedType, object>> field, AdminFieldFlags flags, string displayName = null)
Die Felddaten an das Ansichtsmodell auch zugänglich ist, so in der Ansicht wir Code wie dieses:
@foreach (var f in Model.Fields.Where(f => !f.Hidden))
{
//Gets original expression for this field
var expression = Model.ExpressionFromField<UserViewModel>(f);
<div class="form-group">
@Html.LabelFor(expression, new { @class = "control-label col-3" })
@Html.EditorFor(expression, new { htmlAttributes = new { @class = "form-control" } })
</div>
}
Viola! Die Feldbezeichnung und das Bearbeitungsfeld werden angezeigt!
Das Problem
die Methodensignatur für AdminField
nimmt ein Expression<Func<TMaintainedType, object>>
Objekt. Dies funktioniert hervorragend für string
s, aber (basierend auf meinem begrenzten Verständnis) erzwingt ein Boxen/Unboxing für int
Felder, und damit ändert sich der gespeicherte Ausdruck von (zum Beispiel) u => u.UserId
zu u => Convert(u.UserId)
. Da ich ein Array von Feldern speichern, muss der Rückgabetyp object
sein (da es anders sein kann), so dass ich die Convert
nicht entfernen kann.
Als Ergebnis, wenn das Feld den Ausdruck und das Feld ist int32
packt, erhalte ich eine System.InvalidOperationException
Fehler auf meiner LabelFor Linie: Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.
die Frage
Wie ich Expression<Func<T, object>>
-Expression<Func<T, int>>
umwandeln kann dynamisch?
ich zur Zeit durch die Schaffung einer speziellen Methode nur für ganze Zahlen, um das Problem bekommen, das die Umwandlung entfernt, aber das bedeutet, dass
- I für eine ganze Zahl (jedes Mal überprüfen müssen, die für eine LOT macht von If-Anweisungen in den Ansichten) und
- Wenn ich einen anderen Werttyp brauche, muss ich noch eine andere spezielle Methode erstellen und switch/if-Anweisungen in den Ansichten verwenden, um die richtige Methode auszuwählen.
Hilfe! Lassen Sie mich wissen, wenn Sie weitere Informationen benötigen; es ist immer schwer zu wissen, was zu berücksichtigen ist.
aus Interesse, warum haben Sie nicht einen Typparameter anstelle von Objekt verwendet? z.B. 'Expression>' –
Der Rückgabetyp ist mit 'AdminField' verknüpft. Wenn Sie einen Rückgabetyp-Parameter verwenden, müssen Sie dies in 'AdminField ' ändern. Ich brauche Arrays von 'AdminField' Objekten mit unterschiedlichen Rückgabetypen, das funktioniert nicht. Die einzigen Alternativen, die ich mir vorstellen konnte (z. B. Kovarianz), würden nur mit Referenztypen funktionieren, und die meisten meiner Typen sind Werttypen. –
Daniel
Ich habe mein Gehirn dazu gebracht, es auszuarbeiten, aber noch keine Würfel; interessante Herausforderung;) –