Usa string.Compare (a, b) in Expression

c# expression expression-trees

Domanda

Ho insegnato a me stesso Expression Trees da ieri e sto riscontrando problemi nel confrontare due valori di stringa. Ho fatto questo test case che fallisce con l'errore:

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

Errore in fase di esecuzione a 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));

Utilizzerò i left & right risultanti in un Expression.Equal, LessThan, LessThanOrEqual, GreaterThan or GreaterThanOrEqual . Questo è il motivo del metodo Compare.

Sono sicuro che sia qualcosa di semplice, e ho ridotto il mio codice a questo semplice caso di test. Qualcuno vede dove ho sbagliato?

Risposta accettata

Questo è il problema nel tuo codice Expression.Call :

new Type[] { type, type },

Questo sta cercando di chiamare string.Compare<string, string> - sono gli argomenti generici , non i tipi dei parametri normali. Dato che si tratta di un metodo non generico, basta usare null qui.

Programma breve ma 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());
    }
}

Risposta popolare

Stavo cercando di fare qualcosa di simile a una clausola lambda where ( LINQ to SQL ), e dal momento che varie ricerche mi hanno portato su questa pagina, quindi condividerò una tale soluzione qui nel caso in cui aiuti gli altri che atterrano qui.

È più semplice quando si semplifica ciò che si sta facendo con un'espressione generica di Compare .

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

Quindi puoi usare questa espressione come qualsiasi altra

    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 strega può essere usata come

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

Ciò è utile se si dispone di un elenco di filtri scelti dall'utente che è necessario applicare, in cui è possibile scegliere sia i valori che gli operatori. (Inizia con, Contiene, Tra intervallo)



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché