DataTable上的表达式树

时间:2015-05-15 22:02:41

标签: c# linq expression-trees dynamic-linq

我正在尝试使用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的东西但是我想看看这是如何用表达式树完成的:)

希望有人可以提供帮助。

2 个答案:

答案 0 :(得分:1)

您的谓词必须经过编译才能在您的案例中使用,因为您正在使用IEnumerable<>进行操作。

试试这个:

var qs = qt.Where(pb.Compile());

答案 1 :(得分:1)

您不需要lambda表达式在内存中搜索。不要过分复杂你的生活,只需创建委托(Func&lt; T,bool&gt;)并使用它们,更容易编写,处理和调试!