zoukankan      html  css  js  c++  java
  • 通过LINQ表达式树动态构建查询条件

    第一种方法:

    public static class PredicateExtensions
        {
            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>> Or<T>(this Expression<Func<T, bool>> expression1, 
               Expression<Func<T, bool>> expression2)
            {
                var invokedExpression = Expression.Invoke(expression2, expression1.Parameters
                        .Cast<Expression>());
    
                return Expression.Lambda<Func<T, bool>>(Expression.Or(expression1.Body, invokedExpression),
                expression1.Parameters);
            }
    
            public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, 
                  Expression<Func<T, bool>> expression2)
            {
                var invokedExpression = Expression.Invoke(expression2, expression1.Parameters
                     .Cast<Expression>());
    
                return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, 
                       invokedExpression), expression1.Parameters);
            }
        }

    第二种方法:

        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<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
            {
                // build parameter map (from parameters of second to parameters of first)
                var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
    
                // replace parameters in the second lambda expression with parameters from the first
                var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
    
                // apply composition of lambda expression bodies to parameters from the first expression 
                return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
            }
    
            public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
            {
                return first.Compose(second, Expression.And);
            }
    
            public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
            {
                return first.Compose(second, Expression.Or);
            }
        }
    
        public class ParameterRebinder : ExpressionVisitor
        {
            private readonly Dictionary<ParameterExpression, ParameterExpression> map;
    
            public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
            {
                this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
            }
    
            public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
            {
                return new ParameterRebinder(map).Visit(exp);
            }
    
            protected override Expression VisitParameter(ParameterExpression p)
            {
                ParameterExpression replacement;
                if (map.TryGetValue(p, out replacement))
                {
                    p = replacement;
                }
                return base.VisitParameter(p);
            }
        }

    注意,经我实际应用,发现第一种方法PredicateExtensions类有个缺陷,就是仅适合在DbDataContext中使用,若用在EntityContext中,则会报错:LINQ to Entities 不支持 LINQ 表达式节点类型“Invoke”。而使用第二种方法则不会有这个问题,至于问题的根源我还没有找到原因,还望高手指教,谢谢!

  • 相关阅读:
    5_添加购物车 View+Con
    5_添加购物车 B+M
    5_添加购物车 D
    登录注册V
    bootstrap-标题
    h5整理--详解css的相对定位和绝对定位
    各大门户网站的css初始化代码
    九月二十八JS验证
    js函数和运算符
    4.1原始表达式 9/16
  • 原文地址:https://www.cnblogs.com/zuowj/p/4354755.html
Copyright © 2011-2022 走看看