Verwenden Sie string.Compare (a, b) in Ausdruck

c# expression expression-trees

Frage

Ich lehre mich seit gestern selbst bei Expression Trees und habe Probleme, zwei String-Werte zu vergleichen. Ich habe diesen Testfall erstellt, der mit dem Fehler fehlschlägt:

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

Fällt zur Laufzeit auf der 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));

Ich werde die resultierenden Links und Rechts in einem Expression.Equal, LessThan, LessThanOrEqual, GreaterThan or GreaterThanOrEqual . Das ist der Grund für die Compare-Methode.

Ich bin sicher, es ist etwas Einfaches, und ich habe meinen Code auf diesen einfachen Testfall heruntergekocht. Wer sieht wo ich falsch gelaufen bin?

Akzeptierte Antwort

Dies ist das Problem in Ihrem Expression.Call Code:

new Type[] { type, type },

Das versucht string.Compare<string, string> - das sind die generischen Argumente , nicht die Typen der normalen Parameter. Da es sich um eine nicht-generische Methode handelt, verwenden Sie hier einfach null.

Kurzes aber vollständiges Programm:

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

Beliebte Antwort

Ich habe versucht, eine ähnliche lambda where-Klausel ( LINQ to SQL ) zu erstellen , und da verschiedene Suchen mich auf dieser Seite gelandet haben, werde ich eine solche Lösung hier teilen, falls sie anderen hilft, die hier landen.

Es ist am einfachsten, wenn Sie das, was Sie tun, mit einem generischen Ausdruck des Compare vereinfachen.

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

Dann kannst du diesen Ausdruck wie jeden anderen benutzen

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

Hexe kann wie verwendet werden

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

Dies ist nützlich, wenn Sie eine Liste der vom Benutzer ausgewählten Filter haben, die Sie anwenden müssen, wobei die Werte und Operatoren ausgewählt werden können. (Beginnt mit, enthält zwischen Zwischenbereich)



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum