LINQ to Entities: Combining Predicates

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace ExpressionTest
{
    class Product
    {
        public int ProductId { get; set; }
        public string Text { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Expression<Func<Product, bool>> filter1 = p =>  p.ProductId == 1;
            Expression<Func<Product, bool>> filter2 = p => p.Text.Contains("test");
            Expression<Func<Product, bool>> filter3  = filter1.And(filter2);
            Expression<Func<Product, bool>> filter4 = filter1.Or(filter2);
            List<Product> list = new List<Product>{
                new Product { ProductId=1, Text="test"},
                new Product { ProductId=1, Text="est2"},
                new Product { ProductId=2, Text="test2"}
            };
            Console.WriteLine(list.AsQueryable().Where(filter3));
            list.AsQueryable().Where(filter3).ToList().ForEach(_ => { Console.WriteLine(_.Text); });
            Console.WriteLine(list.AsQueryable().Where(filter4));
            list.AsQueryable().Where(filter4).ToList().ForEach(_ => { Console.WriteLine(_.Text); });
            Console.ReadKey(true);
        }
    }
    public static class ExpressionEx
    {
        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);
        }
    }
}

ss

知识共享许可协议
《LINQ to Entities: Combining Predicates》常伟华 创作。
采用 知识共享 署名-相同方式共享 3.0 中国大陆 许可协议进行许可。
  • 多说评论
  • 签名
  • 新浪微博
  • 默认评论
  • Tab Header 5

0 条评论 / 点击此处发表评论

Tab Content 5

开发技术


开发平台和工具

sitemap     156.46ms