Repository navigation
Expand file tree
/
Copy pathExpressionExtensions.cs
More file actions
125 lines (112 loc) · 4.57 KB
/
Copy pathExpressionExtensions.cs
File metadata and controls
125 lines (112 loc) · 4.57 KB
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
116
117
118
119
120
121
122
123
124
125
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
namespace uComponents.Mapping
{
internal static class ExpressionExtensions
{
/// <summary>
/// Taken from <c>System.Data.Entity.Internal.DbHelpers</c>:
///
/// Called recursively to parse an expression tree representing a property path..
/// This involves parsing simple property accesses like o => o.Products as well as calls to Select like
/// o => o.Products.Select(p => p.OrderLines).
/// </summary>
/// <param name="expression"> The expression to parse. </param>
/// <param name="path"> The expression parsed into an include path, or null if the expression did not match. </param>
/// <returns> True if matching succeeded; false if the expression could not be parsed. </returns>
public static bool TryParsePath(this Expression expression, out string path)
{
if (expression == null)
{
throw new ArgumentNullException("expression");
}
path = null;
var withoutConvert = expression.RemoveConvert(); // Removes boxing
var memberExpression = withoutConvert as MemberExpression;
var callExpression = withoutConvert as MethodCallExpression;
if (memberExpression != null)
{
var thisPart = memberExpression.Member.Name;
string parentPart;
if (!TryParsePath(memberExpression.Expression, out parentPart))
{
return false;
}
path = parentPart == null ? thisPart : (parentPart + "." + thisPart);
}
else if (callExpression != null)
{
if (callExpression.Method.Name == "Select"
&& callExpression.Arguments.Count == 2)
{
string parentPart;
if (!TryParsePath(callExpression.Arguments[0], out parentPart))
{
return false;
}
if (parentPart != null)
{
var subExpression = callExpression.Arguments[1] as LambdaExpression;
if (subExpression != null)
{
string thisPart;
if (!TryParsePath(subExpression.Body, out thisPart))
{
return false;
}
if (thisPart != null)
{
path = parentPart + "." + thisPart;
return true;
}
}
}
}
return false;
}
return true;
}
/// <summary>
/// Removes boxing on the expression.
///
/// Taken from <c>System.Data.Entity.Utilities.ExpressionExtensions</c>.
/// </summary>
public static Expression RemoveConvert(this Expression expression)
{
if (expression == null)
{
throw new ArgumentNullException("expression");
}
while ((expression != null)
&& (expression.NodeType == ExpressionType.Convert
|| expression.NodeType == ExpressionType.ConvertChecked))
{
expression = RemoveConvert(((UnaryExpression)expression).Operand);
}
return expression;
}
/// <summary>
/// Gets property info from a lambda expression.
/// </summary>
/// <param name="expression">The expression indicating the property.</param>
/// <returns>The property info.</returns>
public static PropertyInfo GetPropertyInfo(this LambdaExpression expression)
{
if (expression == null)
{
throw new ArgumentNullException("expression");
}
var withoutConvert = expression.Body.RemoveConvert();
var memberExpression = withoutConvert as MemberExpression;
if (memberExpression == null || memberExpression.Member as PropertyInfo == null)
{
throw new IndexOutOfRangeException("Property expression could not be parsed");
}
return memberExpression.Member as PropertyInfo;
}
}
}