2011-04-05 5 views
14

En aras de la simplicidad, imaginemos el siguiente código:¿Cómo obtengo el valor de una expresión anónima?

Quiero crear una Foo:

public class Foo 
{ 
    public string Bar { get; set; } 
} 

y pasarlo a un método especial HTML Ayudante:

Html.SomeFunction(f => f.Bar); 

que se define como:

public string SomeFunction<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) 

Quiero obtener el valor de Bar dentro de esta función, pero no tengo ni idea de cómo obtenerla.

Respuesta

26

Simplemente compila la expresión y obtén el valor.

Func<TModel, TValue> method = expression.Compile(); 

TValue value = method(html.ViewData.Model); 
// might be a slightly different property, but you can get the ViewModel 
// from the HtmlHelper object. 
+0

Recibo el siguiente error con su código: Error 'System.Web.Mvc.HtmlHelper ' no contiene una definición para 'Modelo' y no Se puede encontrar el método de extensión 'Modelo' que acepta un primer argumento de tipo 'System.Web.Mvc.HtmlHelper ' (¿falta una directiva using o una referencia de ensamblado?) – mynameiscoffey

+2

Debe ser 'html.ViewData.Model'. Mi publicación inicial fue simplemente apresurada con el nombre de la propiedad. – Tejs

+0

+1 Funciona como un encanto, gracias !! – mynameiscoffey

5

Deberá llamar al Compile() en la expresión para obtener el Func y luego ejecutarlo.

public string SomeFunction<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) 
{ 
    TValue valueOfBar = expression.Compile()(html.Model); // Assumes Model is accessible from html. 

    // Do stuff 
} 

Nota al margen: Si no hay ninguna necesidad de que las expresiones dinámicas o análisis de la expresión puede ser que también pasa la Func directamente en su lugar.

+1

+1 Reddog también habla aquí la verdad; si realmente no hay razón para examinar la expresión, simplemente pasar 'Func ' es mucho mejor. – Tejs

+1

Desafortunadamente la Expresión es necesaria para otras interacciones que suceden dentro del método – mynameiscoffey

0

Para aquellos que están utilizando la expresión sin MVT modelo, se podría obtener el nombre y el valor de la propiedad de una manera siguiente.

public static string Meth<T>(Expression<Func<T>> expression) 
{ 
    var name = ((MemberExpression)expression.Body).Member.Name; 
    var value = expression.Compile()(); 
    return string.Format("{0} - {1}", name, value); 
} 

uso:

Meth(() => YourObject.Property); 
0

Usando Compile() utilizará el compilador-marco Roslyn y emitirá MSIL-código que se carga dinámicamente en su aplicación. Este código ejecutable ocupa memoria y, a diferencia de la memoria "normal", no está sujeta a la recolección de basura ni puede liberarla usted mismo. Si lo hace con demasiada frecuencia (como regularmente durante la generación de SQL), finalmente se quedará sin memoria. Me encontré con este tema y de fuentes abiertas mis soluciones como una biblioteca de código abierto:

https://www.nuget.org/packages/MiaPlaza.ExpressionUtils

Cuestiones relacionadas