【问题标题】:LINQ Expression<Func<T, bool>> equavalent of .Contains()LINQ 表达式<Func<T, bool>> 等价于 .Contains()
【发布时间】:2019-11-30 23:27:35
【问题描述】:

有没有人知道如何使用 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);
}

与此类似的东西会是理想的吗?

【问题讨论】:

标签: linq linq-expressions


【解决方案1】:
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这样的一些内容。
  • 返回不起作用,因为Expression.Call要返回MethodCallExpression类型。您应该更改为: var call = Expression.Call(param, contains, Expression.Constant(subString, typeof(string))); return Expression.Lambda>(call, param);
【解决方案2】:

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

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)是字符串类型,因为包含仅对字符串有效,因此您可以改用MethodInfo method = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多