2008-12-31 15 views
63

Los árboles de expresión son una buena característica, pero ¿cuáles son sus usos prácticos? ¿Se pueden usar para algún tipo de generación de código o metaprogramación o algo así?Uso práctico de árboles de expresión

+0

posible duplicado de [¿Cuáles son algunos ejemplos en los que los árboles de expresión son útiles?] (Http://stackoverflow.com/questions/27726/what-are-some-instances-in-which-expression-trees-are- útil) – nawfal

Respuesta

4

Puede usarlos para crear su propio proveedor de linq para un sitio web como Google o Flickr o Amazon, su propio sitio web u otro proveedor de datos.

20

Marc Gravell los ha utilizado con gran efecto en MiscUtil para implementar generic operators.

+11

Darn, vencerme a eso ;-p –

8

La implementación de los proveedores de LINQ se realiza principalmente mediante el procesamiento de árboles de expresiones. También estoy usando ellos para eliminar las cadenas literales de mi código:

41

Como señala Jon, que los utilizan para proporcionar generic operators con .NET 3.5. También los uso (de nuevo en MiscUtil) para proporcionar acceso rápido a constructores no predeterminados (no se puede usar Delegate.CreateDelegate con constructores, pero Expression funciona bien).

Otros usos de los árboles de expresión creados manualmente:

Pero en realidad, la expresión es una forma muy versátil de escribir ningún código dinámico. Mucho más simple que Reflection.Emit, y por mi dinero, más fácil de entender que CodeDOM. Y en .NET 4.0, tiene even more options disponible. Muestro los fundamentos de escribir código a través de Expressionon my blog.

+0

Gracias. el blog no aparece !!! – pixparker

+0

@pixparker Acabo de probarlo: funciona bien –

12

Los uso para crear consultas dinámicas, ya sea para clasificar o filtrar los datos. A modo de ejemplo:

IQueryable<Data.Task> query = ctx.DataContext.Tasks; 

if (criteria.ProjectId != Guid.Empty) 
     query = query.Where(row => row.ProjectId == criteria.ProjectId); 

if (criteria.Status != TaskStatus.NotSet) 
     query = query.Where(row => row.Status == (int)criteria.Status); 

if (criteria.DueDate.DateFrom != DateTime.MinValue) 
     query = query.Where(row => row.DueDate >= criteria.DueDate.DateFrom); 

if (criteria.DueDate.DateTo != DateTime.MaxValue) 
    query = query.Where(row => row.DueDate <= criteria.DueDate.DateTo); 

if (criteria.OpenDate.DateFrom != DateTime.MinValue) 
    query = query.Where(row => row.OpenDate >= criteria.OpenDate.DateFrom); 

var data = query.Select(row => TaskInfo.FetchTaskInfo(row)); 
2

originalmente por Jomo Fisher, Gustavo Guerra publicó una versión revisada de la static string dictionary.

Where through Expression trees, una expresión dinámica que proporciona un diccionario realmente (léase: ridículamente).

La implementación crea un árbol de decisión dinámico que selecciona el valor actual de acuerdo con la longitud de la cadena de entrada, luego con la primera letra, luego con la segunda letra y así sucesivamente.

Esto finalmente se ejecuta mucho más rápido que el diccionario equivalente.

13

acabo de crear un generic filter function usando ExpressionTree .. Quiero share con ustedes ...

Start

var allFiltered= Filter(AllCustomer, "Name", "Moumit"); 

public static List<T> Filter<T>(this List<T> Filterable, string PropertyName, object ParameterValue) 
{ 
    ConstantExpression c = Expression.Constant(ParameterValue); 
    ParameterExpression p = Expression.Parameter(typeof(T), "xx"); 
    MemberExpression m = Expression.PropertyOrField(p, PropertyName); 
    var Lambda = Expression.Lambda<Func<T, Boolean>>(Expression.Equal(c, m), new[] { p }); 
    Func<T, Boolean> func = Lambda.Compile(); 
    return Filterable.Where(func).ToList(); 
} 

One More

string singlePropertyName=GetPropertyName((Property.Customer p) => p.Name); 

public static string GetPropertyName<T, U>(Expression<Func<T, U>> expression) 
{ 
     MemberExpression body = expression.Body as MemberExpression; 
     // if expression is not a member expression 
     if (body == null) 
     { 
      UnaryExpression ubody = (UnaryExpression)expression.Body; 
      body = ubody.Operand as MemberExpression; 
     } 
     return string.Join(".", body.ToString().Split('.').Skip(1)); 
} 

Make it more expandable

string multiCommaSeparatedPropertyNames=GetMultiplePropertyName<Property.Customer>(c => c.CustomerId, c => c.AuthorizationStatus) 

public static string GetMultiplePropertyName<T>(params Expression<Func<T, object>>[] expressions) 
{ 
     string[] propertyNames = new string[expressions.Count()]; 
     for (int i = 0; i < propertyNames.Length; i++) 
     { 
      propertyNames[i] = GetPropertyName(expressions[i]); 
     } 

     return propertyNames.Join(); 
} 

....... Sé que también se puede hacer uso de Reflection ... pero éste es tremendamente rápido o puedo decir equivalente a Lambda después de la primera compilación ... La primera iteración es solo una lenta promedio de 10 milisegundos ... Así que esto es Expression Tree mágico. Simple y fantástico ... ¡¡¡Creo que ... !!!!!!!!

+0

¡Agradable! Gracias por los ejemplos. –

Cuestiones relacionadas