LINQ Expression<Func<T, bool>>中等价于.Contains()的方法是什么?

9

有人知道如何使用Linq表达式创建.Contains(string)函数,或者创建谓词来实现这一点吗?

public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
      Expression<Func<T, bool>> expr2)
{
    var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
    return Expression.Lambda<Func<T, bool>>
               (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}

像这样的东西是理想的吗?

2
先开始接受一些答案,比如这个 http://stackoverflow.com/questions/1648270/how-to-determine-what-happens-behind-the-scene-in-net/1648306#1648306 和这个 http://stackoverflow.com/questions/2331927/linq-to-xml-replace-child-nodes-but-keep-state/2332087#2332087。 - Steven
这里是另一个重复的链接:https://dev59.com/HkjSa4cB1Zd3GeqPJN9t - Kamarey
2个回答

5
public static Expression<Func<string, bool>> StringContains(string subString)
{
    MethodInfo contains = typeof(string).GetMethod("Contains");
    ParameterExpression param = Expression.Parameter(typeof(string), "s");
    var call = Expression.Call(param, contains, Expression.Constant(subString, typeof(string)));
    return Expression.Lambda<Func<string, bool>>(call, param);
}

...

// s => s.Contains("hello")
Expression<Func<string, bool>> predicate = StringContains("hello");

多年后再看这个问题,我突然意识到一个更简单的方法:

Expression<Func<string, bool>> predicate = s => s.Contains("hello");

只是为了明确一点,上面提到的解决方案如果直接使用是行不通的,我只使用了一些内容,比如MethodInfo和ParameterExpression。 - BK.
返回不起作用,是因为Expression.Call希望返回MethodCallExpression类型。您应该更改为以下内容:var call = Expression.Call(param, contains, Expression.Constant(subString, typeof(string))); return Expression.Lambda>(call, param); - Bence Végert

4

我使用类似的方法,在查询中添加过滤器。

public static Expression<Func<TypeOfParent, bool>> PropertyStartsWith<TypeOfParent, TypeOfPropery>(PropertyInfo property, TypeOfPropery value)
{
     var parent = Expression.Parameter(typeof(TypeOfParent));
     MethodInfo method = typeof(string).GetMethod("StartsWith",new Type[] { typeof(TypeOfPropery) });
     var expressionBody = Expression.Call(Expression.Property(parent, property), method, Expression.Constant(value));
     return Expression.Lambda<Func<TypeOfParent, bool>>(expressionBody, parent);
}

使用方法:针对属性名称匹配Key的属性应用过滤器,并使用提供的值Value。

public static IQueryable<T> ApplyParameters<T>(this IQueryable<T> query, List<GridParameter> gridParameters)
{

   // Foreach Parameter in List
   // If Filter Operation is StartsWith
    var propertyInfo = typeof(T).GetProperty(parameter.Key);
    query = query.Where(PropertyStartsWith<T, string>(propertyInfo, parameter.Value));
}

是的,这种方法也适用于包含:

        public static Expression<Func<TypeOfParent, bool>> PropertyContains<TypeOfParent, TypeOfPropery>(PropertyInfo property, TypeOfPropery value)
    {
        var parent = Expression.Parameter(typeof(TypeOfParent));
        MethodInfo method = typeof(string).GetMethod("Contains", new Type[] { typeof(TypeOfPropery) });
        var expressionBody = Expression.Call(Expression.Property(parent, property), method, Expression.Constant(value));
        return Expression.Lambda<Func<TypeOfParent, bool>>(expressionBody, parent);
    }

通过这两个例子,您可以更轻松地理解我们如何通过名称调用各种不同的方法。

在这行代码 MethodInfo method = typeof(string).GetMethod("Contains", new Type[] { typeof(TypeOfPropery) }); 中,你假定 typeof(TypeOfPropery) 是字符串类型,因为 Contains 只适用于字符串,所以你可以使用 MethodInfo method = typeof(string).GetMethod("Contains", new Type[] { typeof(string) }); 替代它。 - Shahar Shokrani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接