1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
| using System;
| using System.Collections.Generic;
| using System.Linq;
| using System.Linq.Expressions;
|
| namespace JiepeiWMS.Extends
| {
| 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, T2, T3, T4, T5, bool>> And<T, T2, T3, T4, T5>(this Expression<Func<T, T2, T3, T4, T5, bool>> first, Expression<Func<T, T2, T3, T4, T5, bool>> second)
| {
| return first.Compose(second, Expression.And);
| }
| public static Expression<Func<T, T2, T3, T4, T5, T6, bool>> And<T, T2, T3, T4, T5, T6>(this Expression<Func<T, T2, T3, T4, T5, T6, bool>> first, Expression<Func<T, T2, T3, T4, T5, T6, 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);
| }
| }
| }
|
|