2

次のようなLinq式のリストがあります。

List<Expression<Func<Customer, bool>>>

次のように、検索ページから一連の述語を追加する必要があります。

x.Name.Contains(searchString)
x.Description.Contains(searchString)
...

大量の重複コードにならないようにメソッドを作成したい。次のような署名のあるもの:

void AddCustomerPredicate(List<Expression<Func<Customer, bool>>> predicates, Expression<Func<Customer, string>> prop, string searchString);

私は次のように使用します:

var predicates = new List<Expression<Func<Customer, bool>>>();
AddCustomerPredicate(predicates, x => x.Name, this.Name);
AddCustomerPredicate(predicates, x => x.Description, this.Description);
...

問題を少し単純化しましたが、それが要点です。式ツリーなどの作業をあまり行っていないので、このメソッドを実装する方法がわかりませんか?

**編集**

問題を単純化しすぎたのかもしれません。のようにリストに追加する方法は知っていますが、リストにpredicates.Add(x => x.Name.Contains(this.searchString))追加する前に各検索パラメーターで実行したいことがいくつかあります (たとえば、null または空のチェック)。したがって、上記のように各検索パラメーターでメソッドを呼び出したいので、そのすべてを単一のメソッドに含めることができます。

4

2 に答える 2

3

本当に必要なのは、に変換Expression<Func<T, string>>するためのメソッドを持つことですExpression<Func<T, bool>>:

public static Expression<Func<T, bool>> GetContainsExpression<T>(Expression<Func<T, string>> prop, string searchString)
{
    var method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
    var someValue = Expression.Constant(searchString, typeof(string));
    var containsMethodExp = Expression.Call(prop.Body, method, someValue);

    return Expression.Lambda<Func<T, bool>>(containsMethodExp, prop.Parameters[0]);
}

これは、C# で 'String.Contains(“term”)' を表す式ツリーを作成するにはどうすればよいですか? という別の回答に触発されています。

var predicates = new List<Expression<Func<Customer, bool>>>();
predicates.Add(GetContainsExpression((Customer x) => x.Name, this.Name));
predicates.Add(GetContainsExpression((Customer x) => x.Description, this.Description));
于 2013-11-05T15:47:14.330 に答える
2

私はこれがあなたが望むことを行い、nullプロパティ値も処理すると信じています(呼び出しContains()はスローしません):

private static void AddCustomerPredicate(
    List<Expression<Func<Customer, bool>>> predicates,
    Expression<Func<Customer, string>> accessor,
    string searchString)
{
    var x = accessor.Parameters[0];
    var temp = Expression.Variable(typeof(string), "temp");

    var predicate = Expression.Lambda<Func<Customer, bool>>(
        Expression.Block(
            new[] { temp },
            Expression.Assign(
                temp,
                accessor.Body),
            Expression.AndAlso(
                Expression.IsFalse(
                    Expression.ReferenceEqual(
                        temp,
                        Expression.Default(typeof(string)))),
                Expression.Call(
                    temp,
                    "Contains",
                    Type.EmptyTypes,
                    Expression.Constant(searchString)))),
        x);

    predicates.Add(predicate);
}
于 2013-11-05T15:41:24.007 に答える