forked from ServiceStack/ServiceStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExpressionUtils.cs
More file actions
130 lines (109 loc) · 4.64 KB
/
ExpressionUtils.cs
File metadata and controls
130 lines (109 loc) · 4.64 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
126
127
128
129
130
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using ServiceStack.Logging;
namespace ServiceStack
{
public static class ExpressionUtils
{
private static readonly ILog Log = LogManager.GetLogger(typeof(ExpressionUtils));
public static PropertyInfo ToPropertyInfo(this Expression fieldExpr)
{
return ToPropertyInfo(fieldExpr as LambdaExpression)
?? ToPropertyInfo(fieldExpr as MemberExpression);
}
public static PropertyInfo ToPropertyInfo(LambdaExpression lambda)
{
return lambda?.Body.NodeType == ExpressionType.MemberAccess
? ToPropertyInfo(lambda.Body as MemberExpression)
: null;
}
public static PropertyInfo ToPropertyInfo(MemberExpression m)
{
var pi = m?.Member as PropertyInfo;
return pi;
}
public static string GetMemberName<T>(Expression<Func<T, object>> fieldExpr)
{
var m = GetMemberExpression(fieldExpr);
if (m != null)
return m.Member.Name;
throw new NotSupportedException("Expected Property Expression");
}
public static MemberExpression GetMemberExpression<T>(Expression<Func<T, object>> expr)
{
var member = expr.Body as MemberExpression;
var unary = expr.Body as UnaryExpression;
return member ?? unary?.Operand as MemberExpression;
}
public static Dictionary<string, object> AssignedValues<T>(this Expression<Func<T>> expr)
{
if (!(expr?.Body is MemberInitExpression initExpr))
return null;
var to = new Dictionary<string, object>();
foreach (MemberBinding binding in initExpr.Bindings)
{
to[binding.Member.Name] = binding.GetValue();
}
return to;
}
public static string[] GetFieldNames<T>(this Expression<Func<T, object>> expr)
{
if (expr.Body is MemberExpression member)
{
if (member.Member.DeclaringType.IsAssignableFrom(typeof(T)))
return new[] { member.Member.Name };
var array = CachedExpressionCompiler.Evaluate(member);
if (array is IEnumerable<string> strEnum)
return strEnum.ToArray();
}
if (expr.Body is NewExpression newExpr)
return newExpr.Arguments.OfType<MemberExpression>().Select(x => x.Member.Name).ToArray();
if (expr.Body is MemberInitExpression init)
return init.Bindings.Select(x => x.Member.Name).ToArray();
if (expr.Body is NewArrayExpression newArray)
{
var constantExprs = newArray.Expressions.OfType<ConstantExpression>().ToList();
if (newArray.Expressions.Count == constantExprs.Count)
return constantExprs.Select(x => x.Value.ToString()).ToArray();
var array = CachedExpressionCompiler.Evaluate(newArray);
if (array is string[] strArray)
return strArray;
return array.ConvertTo<string[]>();
}
if (expr.Body is UnaryExpression unary)
{
member = unary.Operand as MemberExpression;
if (member != null)
return new[] { member.Member.Name };
}
throw new ArgumentException("Invalid Fields List Expression: " + expr);
}
public static object GetValue(this MemberBinding binding)
{
switch (binding.BindingType)
{
case MemberBindingType.Assignment:
var assign = (MemberAssignment)binding;
if (assign.Expression is ConstantExpression constant)
return constant.Value;
try
{
return CachedExpressionCompiler.Evaluate(assign.Expression);
}
catch (Exception ex)
{
Log.Error("Error compiling expression in MemberBinding.GetValue()", ex);
//Fallback to compile and execute
var member = Expression.Convert(assign.Expression, typeof(object));
var lambda = Expression.Lambda<Func<object>>(member);
var getter = lambda.Compile();
return getter();
}
}
return null;
}
}
}