Usa string.Compare (a, b) en Expression

c# expression expression-trees

Pregunta

He estado enseñándome árboles de expresión desde ayer y tengo problemas para comparar dos valores de cadena. He hecho este caso de prueba que falla con el error:

No method 'Compare' on type 'System.String' is compatible with the supplied arguments.

Falla en el tiempo de ejecución a la left = Expression.Call(

Type type = typeof(string);
Expression left, right;
left = Expression.Constant("1", type);
right = Expression.Constant("2", type);
// fails at run-time on the next statement
left = Expression.Call(
    typeof(string),
    "Compare",
    new Type[] { type, type },
    new Expression[] { left, right });
right = Expression.Constant(0, typeof(int));

Expression.Equal, LessThan, LessThanOrEqual, GreaterThan or GreaterThanOrEqual la izquierda y la derecha resultantes en Expression.Equal, LessThan, LessThanOrEqual, GreaterThan or GreaterThanOrEqual . Esa es la razón para el método de comparación.

Estoy seguro de que es algo simple, y he reducido mi código a este sencillo caso de prueba. ¿Alguien ve donde me he equivocado?

Respuesta aceptada

Este es el problema en su código de Expression.Call :

new Type[] { type, type },

Eso es intentar llamar a string.Compare<string, string> : son los argumentos genéricos , no los tipos de los parámetros normales. Dado que es un método no genérico, solo usa null aquí.

Programa corto pero completo:

using System;
using System.Linq.Expressions;

class Test
{
    static void Main()
    {
        var left = Expression.Constant("1", typeof(string));
        var right = Expression.Constant("2", typeof(string));
        var compare = Expression.Call(typeof(string),
                                      "Compare",
                                      null,
                                      new[] { left, right });
        var compiled = Expression.Lambda<Func<int>>(compare).Compile();
        Console.WriteLine(compiled());
    }
}

Respuesta popular

Estaba tratando de hacer lo mismo que una cláusula lambda where ( LINQ to SQL ), y dado que varias búsquedas me llevaron a esta página, compartiré esa solución aquí en caso de que ayude a otros que aterrizan aquí.

Es más fácil cuando simplifica lo que está haciendo con una expresión genérica de la Comparación .

    public static Expression CompareLessThanOrEqualTo(Expression e1, Expression e2)
    {
        var compare = Expression.Call(typeof(string),
                           "Compare",
                           null,
                           new[] { e1, e2 });

        return Expression.LessThanOrEqual(compare, Expression.Constant(0));
    }

Entonces puedes usar esta expresión como cualquier otra.

    public static Expression<Func<TypeOfParent, bool>> PropertyLessThanOrEqualString<TypeOfParent, String>(PropertyInfo property, String value)
    {
        var parent = Expression.Parameter(typeof(TypeOfParent));
        var expressionBody = CompareLessThanOrEqualTo(Expression.Property(parent, property), Expression.Constant(value));
        return Expression.Lambda<Func<TypeOfParent, bool>>(expressionBody, parent);
    }

La bruja puede ser utilizada como

public static IQueryable<T> ApplyFilters<T>(this IQueryable<T> query, List<GridFilters> gridFilters)
{
    // foreach filter
        // Get property (propertyInfo)
        // Get Value(s)
        // Apply Filter
        query = query.Where(PropertyLessThanOrEqualString<T, string>(propertyInfo, value1));

    // ...

    return query;
}

Esto es útil si tiene una lista de filtros elegidos por el usuario que necesita aplicar, donde se pueden elegir los valores y los operadores. (Comienza con, contiene, entre rango)



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