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))如 因此,我想如上所述在每个搜索参数上调用一个方法,因此所有这些东西都可以包含在一个方法中。

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 回答