我正在尝试使用ExpressionTrees
构建一个DataTable过滤器,现在我创建了一个QueryBuilder
帮助程序类,如下所示。电话会是这样的:
var pb = PredicateBuilder.True<DataRowCollection>();
int i = 0;
foreach (var key in keys)
{
pb.And<DataRowCollection>(QueryBuilder.CompareProperty<DataRowCollection>(key.Code, value[key.Code]));
i++;
}
var qs = qt.Where(pb);
现在我遇到的问题是我得到了这样的错误:
'System.Data.EnumerableRowCollection<System.Data.DataRow>' does not contain a definition for 'Where' and the best extension method overload 'System.Data.EnumerableRowCollectionExtensions.Where<TRow>(System.Data.EnumerableRowCollection<TRow>, System.Func<TRow,bool>)' has some invalid argument
Argument 2: cannot convert from 'System.Linq.Expressions.Expression<System.Func<System.Data.DataRowCollection,bool>>' to 'System.Func<System.Data.DataRow,bool>'
助手班:
public class QueryBuilder
{
public static Expression<Func<T, bool>> Compare<T>(T rhs, ExpressionType op)
{
var lhsParam = Expression.Parameter(typeof(T), "x");
var rhsParam = Expression.Constant(rhs);
var binaryExp = Expression.MakeBinary(op, lhsParam, rhsParam);
var theLambda = Expression.Lambda<Func<T, bool>>(binaryExp, lhsParam);
return theLambda;
}
public static Expression<Func<T, bool>> Between<T>(T lower, T upper)
{
var predicateInner = PredicateBuilder.True<T>();
predicateInner = predicateInner.And(Compare<T>(lower, ExpressionType.GreaterThan));
predicateInner = predicateInner.And(Compare<T>(upper, ExpressionType.LessThan));
return predicateInner;
}
public static Expression<Func<T,bool>> CompareProperty<T>(string propertyName, dynamic criteria)
{
ParameterExpression pe = Expression.Parameter(typeof(T), "t");
Expression np = Expression.Property(pe, propertyName);
ConstantExpression value = Expression.Constant(criteria);
Expression eq = Expression.Equal(np, value);
var filter = Expression.Lambda<Func<T, bool>>(eq, pe);
return filter;
}
}
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> True<T>(IQueryable<T> query) { return f => true; }
public static Expression<Func<T, bool>> False<T>(IQueryable<T> query) { return f => false; }
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);
}
public static Expression<Func<T, bool>> And<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.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
我知道有一些叫做动态Linq的东西但是我想看看这是如何用表达式树完成的:)
希望有人可以提供帮助。
答案 0 :(得分:1)
您的谓词必须经过编译才能在您的案例中使用,因为您正在使用IEnumerable<>
进行操作。
试试这个:
var qs = qt.Where(pb.Compile());
答案 1 :(得分:1)
您不需要lambda表达式在内存中搜索。不要过分复杂你的生活,只需创建委托(Func&lt; T,bool&gt;)并使用它们,更容易编写,处理和调试!