2010-12-29 14 views
7

Actualmente, tengo este método para comparar dos números¿Cómo crear un árbol de expresión que hacer lo mismo que "StartsWith"

Private Function ETForGreaterThan(ByVal query As IQueryable(Of T), ByVal propertyValue As Object, ByVal propertyInfo As PropertyInfo) As IQueryable(Of T) 

    Dim e As ParameterExpression = Expression.Parameter(GetType(T), "e") 
    Dim m As MemberExpression = Expression.MakeMemberAccess(e, propertyInfo) 
    Dim c As ConstantExpression = Expression.Constant(propertyValue, propertyValue.GetType()) 
    Dim b As BinaryExpression = Expression.GreaterThan(m, c) 
    Dim lambda As Expression(Of Func(Of T, Boolean)) = Expression.Lambda(Of Func(Of T, Boolean))(b, e) 
    Return query.Where(lambda) 

End Function 

Trabaja muy bien y se consume de esta manera

query = ETForGreaterThan(query, Value, propertyInfo) 

Como puede ver, le doy una colección IQueryable y le agrega una cláusula where, basada en una propiedad y un valor. Y puede construir equivalentes Lessthan, LessOrEqualThan, etc., como System.Linq.Expressions.Expression tiene estos operadores predefinidos.

¿Cómo puedo transformar este código para hacer lo mismo con las cadenas? System.Linq.Expressions.Expression no me da un operador predefinido como "contains" o "startwith" y realmente soy novato con los árboles de Expression.

Gracias, y por favor Publique su respuesta en C#/VB. Elige el que te haga sentir más cómodo.

Respuesta

17
using System; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Reflection; 

namespace WindowsFormsApplication1 
{ 
    static class Program 
    { 
     [STAThread] 
     static void Main() 
     { 
      using (var context = new NorthwindEntities()) 
      { 
       PropertyInfo propertyInfo = typeof(Customer).GetProperty("CustomerID"); 

       IQueryable<Customer> query = context.Customers; 
       query = ETForStartsWith<Customer>(query, "A", propertyInfo); 
       var list = query.ToList(); 
      } 
     } 

     static IQueryable<T> ETForStartsWith<T>(IQueryable<T> query, string propertyValue, PropertyInfo propertyInfo) 
     { 
      ParameterExpression e = Expression.Parameter(typeof(T), "e"); 
      MemberExpression m = Expression.MakeMemberAccess(e, propertyInfo); 
      ConstantExpression c = Expression.Constant(propertyValue, typeof(string)); 
      MethodInfo mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) }); 
      Expression call = Expression.Call(m, mi, c); 

      Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(call, e); 
      return query.Where(lambda); 
     } 
    } 
} 
+0

Probado y trabajando de nuevo. Dos veces menos de 24 h. Tom, ¿hay alguna posibilidad de comprar una cerveza para ti? : D Gracias, de hecho. – Jonathan

+0

Tom - usted señor es un héroe – whiteshooz

4

No es un operador, sino un método, por lo que puede llamarlo con Expression.Call(), donde el parámetro methodinfo será typeof (string) .GetMethod ("StartsWith").

+0

Estoy leyendo sobre ello, pero antes no usaba expression-trees. ¿Podrías darme un ejemplo, por favor? – Jonathan

Cuestiones relacionadas