我正在尝试与ExpressionTrees
建立一个数据表过滤器,现在我制作了一个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的东西,但我想看看这是如何用表达式树完成的:)
希望有人能帮忙
您的谓词必须被编译以在您的情况下可用,因为您在IEnumerable<>
上操作。
试试这个:
var qs = qt.Where(pb.Compile());
不需要lambda表达式在内存中搜索。不要使您的生活过于复杂,只需创建委托(Func<T,>)并使用它们,编写、处理和调试要容易得多!