Cómo crear un árbol de expresiones para hacer lo mismo que "StartsWith"

.net c# expression-trees lambda vb.net

Pregunta

Actualmente, tengo este método para comparar dos números.

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

Funciona bien y se consume de esta manera.

query = ETForGreaterThan(query, Value, propertyInfo)

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

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

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

Respuesta aceptada

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);
        }
    }
}

Respuesta popular

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").



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow