1

昨日から式ツリーを独学で学んでいますが、2 つの文字列値の比較に問題があります。エラーで失敗するこのテスト ケースを作成しました。

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

で実行時に失敗する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. これが Compare メソッドの理由です。

私はそれが単純なものであると確信しており、コードをこの単純なテスト ケースに煮詰めました。私がどこを間違えたのか、誰にもわかりますか?

4

2 に答える 2

12

これはあなたのExpression.Callコードの問題です:

new Type[] { type, type },

それは呼び出そうとしていますstring.Compare<string, string>- それらは一般的な引数であり、通常のパラメータの型ではありません。これは非ジェネリック メソッドであるため、ここでは null を使用してください。

短いが完全なプログラム:

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());
    }
}
于 2012-05-10T18:31:38.747 に答える
2

私はラムダ where 句 ( LINQ to SQL )と同様のことをしようとしていましたが、さまざまな検索でこのページにたどり着いたので、ここにたどり着いた他の人に役立つ場合に備えて、そのような解決策をここで共有します。

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

次に、この式を他の式と同じように使用できます

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

魔女は次のように使用できます

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

これは、適用する必要があるユーザーが選択したフィルターのリストがあり、値と演算子の両方を選択できる場合に便利です。(開始、含む、範囲内)

于 2016-04-22T18:15:46.367 に答える