samedi 3 octobre 2009

Asp.net MVC Editors using lambda expressions

Asp.net MVC c'est génial mais ASP.net MVC 2 sera encore mieux, notamment grâce à une amélioration des helpers et des méthodes d'extensions des vues permettant de typer l'accès aux membres du model grâce aux expressions lambda.

Si vous ne voulez pas attendre et que vous voulez vous aussi pouvoir écrire :


<%= Html.TextBoxFor(Model, m => m.Libelle) %>


la suite vas vous intéresser.

Commencez par écrire une classe permettant de stocker pour un membre de classe, son type, son nom et sa valeur :



class PropertyDef
{
public Type Type { get; private set; }
public string Name { get; private set; }
public object Value { get; private set; }

public PropertyDef(Type type, String name, object value)
{
this.Type = type;
this.Name = name;
this.Value = value;
}
}



Ensuite nous allons devoir créer un helper permettant de parser une expression lambda récupérer précisément ces éléments :



static class LambdaExpressionParser
{
internal static PropertyDef GetPropertyDef<TModel, TValue>(
this Expression<Func<TModel, TValue>> expression, TModel model)
{
ExpressionType nodeType = expression.Body.NodeType;
if (nodeType != ExpressionType.MemberAccess)
throw new InvalidOperationException("MemberAccess expression type needed");

// Récupération de la propriété et de son type
MemberExpression body = (MemberExpression)expression.Body;
MemberInfo member = body.Member;
var name = member.Name;
var type = typeof(TValue);

// Récupération de la valeur
object value = null;
try { value = expression.Compile()(model); }
catch (NullReferenceException) { }

return new PropertyDef(type, name, value);
}
}



Et maintenant, il ne reste plus qu'à encapsuler l'usage d'une méthode d'extension ASP.net MVC dans notre propre méthode d'extension :



public static string TextBoxFor<TModel, TValue>(this HtmlHelper html, TModel model, Expression<Func<TModel, TValue>> expression)
{
var def = LambdaExpressionParser.GetPropertyDef(expression, model);
return System.Web.Mvc.Html.InputExtensions.TextBox(html, def.Name, def.Value);
}



A noter que l'implémentation de MVC 2 sera bien plus pratique puisque les ViewPage vont exposer un HtmlHelper générique qui permet de raccourcir encore la syntaxe (voir l'article de Scott Guthrie).
Et voilà ! vivement ASP.net MVC 2.

Aucun commentaire: