2010-09-23 24 views
10

Estoy intentando escribir un ayudante inflexible que sería algo como esto:Obtener cadena de nombre de la propiedad de la expresión

Html.Lookup(x => x.FooId); 

por ahora tengo esto:

public static MvcHtmlString Lookup<T,TReturn>(this HtmlHelper<T> html, Func<T, TReturn> expression) 
     { 
      // get string "FooId" here 
     } 

nadie sabe cómo para obtener esto?

+0

posible duplicado de [Obtener la propiedad, como una cadena, de una expresión >] (http://stackoverflow.com/questions/2789504/get-the-property-as-a-string-from-an-expressionfunctmodel-tproperty) –

+1

¿Por qué estás reinventando? 'ViewData.ModelMetadata'? –

+0

@Craig Stuntz Realmente no entiendo lo que quiere decir, solo quiero crear un ayudante fuertemente tipado – Omu

Respuesta

22
public static class ExpressionsExtractor 
{ 
    public static string Lookup<T, TProp>(this HtmlHelper<T> html, Expression<Func<T, TProp>> expression) 
    { 
     var memberExpression = expression.Body as MemberExpression; 

     if (memberExpression == null) 
      return null; 

     return memberExpression.Member.Name; 
    } 
} 

A continuación, llamarlo con:

var propName = Html.Lookup(x => x.FooId); 
+0

Creo que esto debería funcionar, pero parece que no he declarado mi expresión correctamente o algo porque no puedo usarlo. Lo que quería – Omu

+0

He editado mi pregunta ahora es la forma en que debería – Omu

+0

Editado la respuesta para que coincida con su pregunta actualizada. –

12

Sin embargo, otro código.

public MvcHtmlString Lookup<T, TReturn>(this HtmlHelper<T> html, Expression<Func<T, TReturn>> expression) 
{ 
    return MvcHtmlString.Create(ExpressionHelper.GetExpressionText(expression)); 
} 

Usar la clase ExpressionHelper. Func es delegado, Expression genera ExpressionTree en tiempo de compilación. Expression.Compile() devuelve delegado, pero Func no obtiene ExpressionTree en tiempo de ejecución.

+1

Yo preferiría esto, porque el framework Mvc lo usa. –

+0

Esto también devuelve el "Class.PropertName" en contra de la respuesta aceptada anteriormente. –

8

Actualmente el uso de esta clase cuando necesito esta funcionalidad fuera del proyecto web donde System.Web.Mvc referencia no debería existir:

namespace Interreg.Domain{ 
    using System; 
    using System.Linq.Expressions; 
    public class PropertyName{ 
    public static string For<T>(
     Expression<Func<T,object>> expression){ 
     var body=expression.Body; 
     return GetMemberName(body); 
    } 
    public static string For(
     Expression<Func<object>> expression){ 
     var body=expression.Body; 
     return GetMemberName(body); 
    } 
    public static string GetMemberName(
     Expression expression){ 
     if(expression is MemberExpression){ 
     var memberExpression=(MemberExpression)expression; 
     if(memberExpression.Expression.NodeType== 
      ExpressionType.MemberAccess) 
      return GetMemberName(memberExpression.Expression)+"."+memberExpression.Member.Name; 
     return memberExpression.Member.Name; 
     } 
     if(expression is UnaryExpression){ 
     var unaryExpression=(UnaryExpression)expression; 
     if(unaryExpression.NodeType!=ExpressionType.Convert) 
      throw new Exception(string.Format("Cannot interpret member from {0}",expression)); 
     return GetMemberName(unaryExpression.Operand); 
     } 
     throw new Exception(string.Format("Could not determine member from {0}",expression)); 
    } 
    } 
} 

Lo bueno de este es - no pierde puntos cuando se va más profundo que sólo una nivel.

0

un poco tarde, pero estoy publicando una solución simple que funciona para mí en .Net 4. Se ha manipulación de los tipos de valor en la línea 4

public PropertyInfo GetPropertyInfo<TSource>(Expression<Func<TSource, object>> propertyLambda) { 
     var member = propertyLambda.Body as MemberExpression; 
     if (member == null) {// value types return Convert(x.property) which can't be cast to MemberExpression 
      var expression = propertyLambda.Body as UnaryExpression; 
      member = expression.Operand as MemberExpression; 
     } 
     return member.Member as PropertyInfo; 
    } 
Cuestiones relacionadas