-
Notifications
You must be signed in to change notification settings - Fork 1k
/
Copy pathCollectionPropertyColumnFilterDescriptor.cs
115 lines (97 loc) · 3.67 KB
/
CollectionPropertyColumnFilterDescriptor.cs
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;
using Telerik.Windows.Data;
using System.Collections.Generic;
namespace FilteringCollectionProperties
{
public class CollectionPropertyColumnFilterDescriptor : MemberColumnFilterDescriptor
{
private static readonly MethodInfo EnumerableCastMethod = typeof(Enumerable).GetMethod("Cast");
private static MethodInfo GenericContainsMethod = GetGenericContainsMethodInfo();
public CollectionPropertyColumnFilterDescriptor(GridViewColumn column) : base(column)
{
}
private static MethodInfo GetGenericContainsMethodInfo()
{
// get the Enumerable.Contains<TSource>(IEnumerable<TSource> source, TSource value) method,
// because it is impossible to get it through Type.GetMethod().
var methodCall = ((MethodCallExpression)((Expression<Func<IEnumerable<object>, bool>>)(source => source.Contains(null))).Body).Method.GetGenericMethodDefinition();
return methodCall.MakeGenericMethod(typeof(object));
}
public override Expression CreateFilterExpression(Expression instance)
{
// WorkingDays
string propertyName = base.Member;
// person.WorkingDays
MemberExpression collectionPropertyAccessor = Expression.Property(instance, propertyName);
// person.WorkingDays.Cast<object>()
MethodCallExpression genericCollectionPropertyAccessor = Expression.Call(null
, EnumerableCastMethod.MakeGenericMethod(new[] { typeof(object) })
, collectionPropertyAccessor);
IFieldFilterDescriptor fieldFilter = ((IColumnFilterDescriptor)this).FieldFilter;
Expression f1Expression = null;
if (fieldFilter.Filter1.Value != FilterDescriptor.UnsetValue)
{
// Build the UPPER field filter, i.e. field filter 1
// "Monday"
ConstantExpression f1Value = Expression.Constant(fieldFilter.Filter1.Value);
// person.WorkingDays.Cast<object>().Contains("Monday")
f1Expression = Expression.Call(
CollectionPropertyColumnFilterDescriptor.GenericContainsMethod
, genericCollectionPropertyAccessor
, f1Value);
if (fieldFilter.Filter1.Operator == FilterOperator.DoesNotContain)
{
// !person.WorkingDays.Cast<object>().Contains("Monday")
f1Expression = Expression.Not(f1Expression);
}
}
Expression f2Expression = null;
if (fieldFilter.Filter2.Value != FilterDescriptor.UnsetValue)
{
// Build the LOWER field filter, i.e. field filter 2
// "Tuesday"
ConstantExpression f2Value = Expression.Constant(fieldFilter.Filter2.Value);
// person.WorkingDays.Cast<object>().Contains("Tuesday")
f2Expression = Expression.Call(
CollectionPropertyColumnFilterDescriptor.GenericContainsMethod
, genericCollectionPropertyAccessor
, f2Value);
if (fieldFilter.Filter2.Operator == FilterOperator.DoesNotContain)
{
// !person.WorkingDays.Cast<object>().Contains("Tuesday")
f2Expression = Expression.Not(f2Expression);
}
}
if (f1Expression == null)
{
if (f2Expression != null)
{
return f2Expression;
}
return Expression.Constant(true);
}
if (f2Expression == null)
{
if (f1Expression != null)
{
return f1Expression;
}
return Expression.Constant(true);
}
switch (fieldFilter.LogicalOperator)
{
case FilterCompositionLogicalOperator.And:
return Expression.And(f1Expression, f2Expression);
case FilterCompositionLogicalOperator.Or:
return Expression.Or(f1Expression, f2Expression);
default:
throw new InvalidOperationException();
}
}
}
}