Skip to content

Commit b598ba3

Browse files
committed
Separate ExpressionVisitor from FieldResolver
1 parent ce491b4 commit b598ba3

File tree

4 files changed

+130
-126
lines changed

4 files changed

+130
-126
lines changed

Diff for: src/Nest/CommonAbstractions/ConnectionSettings/ConnectionSettings.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public TConnectionSettings MapIdPropertyFor<TDocument>(Expression<Func<TDocument
156156
{
157157
objectPath.ThrowIfNull(nameof(objectPath));
158158

159-
var memberInfo = new MemberInfoResolver(this, objectPath);
159+
var memberInfo = new MemberInfoResolver(objectPath);
160160
var fieldName = memberInfo.Members.Single().Name;
161161

162162
if (this._idProperties.ContainsKey(typeof(TDocument)))
@@ -190,7 +190,7 @@ private void ApplyPropertyMappings<TDocument>(IList<IClrTypePropertyMapping<TDoc
190190
foreach (var mapping in mappings)
191191
{
192192
var e = mapping.Property;
193-
var memberInfoResolver = new MemberInfoResolver(this, e);
193+
var memberInfoResolver = new MemberInfoResolver(e);
194194
if (memberInfoResolver.Members.Count > 1)
195195
throw new ArgumentException("MapFieldNameFor can only map direct properties");
196196

Diff for: src/Nest/CommonAbstractions/ConnectionSettings/MemberInfoResolver.cs

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@ namespace Nest
77
/// <summary>
88
/// Resolves member infos in an expression, instance may NOT be shared.
99
/// </summary>
10-
public class MemberInfoResolver : FieldResolver
10+
public class MemberInfoResolver : ExpressionVisitor
1111
{
1212
private readonly IList<MemberInfo> _members = new List<MemberInfo>();
1313
public IList<MemberInfo> Members { get { return _members; } }
1414

15-
public MemberInfoResolver(IConnectionSettingsValues settings, Expression expression) : base(settings)
15+
public MemberInfoResolver(Expression expression)
1616
{
17-
Stack = new Stack<string>();
1817
base.Visit(expression);
1918
}
2019

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Collections.ObjectModel;
5+
using System.Linq;
6+
using System.Linq.Expressions;
7+
using System.Reflection;
8+
using System.Runtime.CompilerServices;
9+
using System.Text;
10+
using System.Threading.Tasks;
11+
12+
namespace Nest
13+
{
14+
internal class FieldExpressionVisitor : ExpressionVisitor
15+
{
16+
private Stack<string> _stack = new Stack<string>();
17+
18+
private IConnectionSettingsValues _settings;
19+
20+
public FieldExpressionVisitor(IConnectionSettingsValues settings)
21+
{
22+
_settings = settings;
23+
}
24+
25+
public string Resolve(Expression expression, bool toLastToken = false)
26+
{
27+
Visit(expression);
28+
if (toLastToken) return _stack.Last();
29+
return _stack
30+
.Aggregate(
31+
new StringBuilder(),
32+
(sb, name) =>
33+
(sb.Length > 0 ? sb.Append(".") : sb).Append(name))
34+
.ToString();
35+
}
36+
37+
public string Resolve(MemberInfo info)
38+
{
39+
if (info == null)
40+
return null;
41+
42+
var name = info.Name;
43+
44+
IPropertyMapping propertyMapping = null;
45+
if (this._settings.PropertyMappings.TryGetValue(info, out propertyMapping))
46+
return propertyMapping.Name;
47+
48+
var att = ElasticsearchPropertyAttribute.From(info);
49+
if (att != null && !att.Name.IsNullOrEmpty())
50+
return att.Name;
51+
52+
return _settings.Serializer?.CreatePropertyName(info) ?? _settings.DefaultFieldNameInferrer(name);
53+
}
54+
55+
protected override Expression VisitMember(MemberExpression expression)
56+
{
57+
if (_stack == null) return base.VisitMember(expression);
58+
var name = this.Resolve(expression.Member);
59+
_stack.Push(name);
60+
return base.VisitMember(expression);
61+
}
62+
63+
protected override Expression VisitMethodCall(MethodCallExpression methodCall)
64+
{
65+
if (methodCall.Method.Name == "Suffix" && methodCall.Arguments.Any())
66+
{
67+
VisitConstantOrVariable(methodCall, _stack);
68+
var callingMember = new ReadOnlyCollection<Expression>(
69+
new List<Expression> { { methodCall.Arguments.First() } }
70+
);
71+
base.Visit(callingMember);
72+
return methodCall;
73+
}
74+
else if (methodCall.Method.Name == "get_Item" && methodCall.Arguments.Any())
75+
{
76+
var t = methodCall.Object.Type;
77+
var isDict =
78+
typeof(IDictionary).IsAssignableFrom(t)
79+
|| typeof(IDictionary<,>).IsAssignableFrom(t)
80+
|| (t.IsGeneric() && t.GetGenericTypeDefinition() == typeof(IDictionary<,>));
81+
82+
if (!isDict)
83+
{
84+
return base.VisitMethodCall(methodCall);
85+
}
86+
VisitConstantOrVariable(methodCall, _stack);
87+
Visit(methodCall.Object);
88+
return methodCall;
89+
}
90+
else if (IsLinqOperator(methodCall.Method))
91+
{
92+
for (int i = 1; i < methodCall.Arguments.Count; i++)
93+
{
94+
Visit(methodCall.Arguments[i]);
95+
}
96+
Visit(methodCall.Arguments[0]);
97+
return methodCall;
98+
}
99+
return base.VisitMethodCall(methodCall);
100+
}
101+
102+
private static void VisitConstantOrVariable(MethodCallExpression methodCall, Stack<string> stack)
103+
{
104+
var lastArg = methodCall.Arguments.Last();
105+
var constantExpression = lastArg as ConstantExpression;
106+
var value = constantExpression != null
107+
? constantExpression.Value.ToString()
108+
: Expression.Lambda(lastArg).Compile().DynamicInvoke().ToString();
109+
stack.Push(value);
110+
}
111+
112+
private static bool IsLinqOperator(MethodInfo methodInfo)
113+
{
114+
if (methodInfo.DeclaringType != typeof(Queryable) && methodInfo.DeclaringType != typeof(Enumerable))
115+
return false;
116+
117+
return methodInfo.GetCustomAttribute<ExtensionAttribute>() != null;
118+
}
119+
}
120+
}

Diff for: src/Nest/CommonAbstractions/Infer/Field/FieldResolver.cs

+6-121
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
namespace Nest
1414
{
15-
public class FieldResolver : ExpressionVisitor
15+
public class FieldResolver
1616
{
1717
private readonly IConnectionSettingsValues _settings;
1818

@@ -51,139 +51,24 @@ public string Resolve(PropertyName property)
5151
string f;
5252
if (this.Properties.TryGetValue(property, out f))
5353
return f;
54-
f = this.ResolveToLastToken(property.Expression, property.Property);
54+
f = this.Resolve(property.Expression, property.Property, true);
5555
this.Properties.TryAdd(property, f);
5656
return f;
5757
}
5858

59-
private string Resolve(Expression expression, MemberInfo member)
59+
private string Resolve(Expression expression, MemberInfo member, bool toLastToken = false)
6060
{
61+
var visitor = new FieldExpressionVisitor(_settings);
6162
var name = expression != null
62-
? this.Resolve(expression)
63+
? visitor.Resolve(expression, toLastToken)
6364
: member != null
64-
? this.Resolve(member)
65+
? visitor.Resolve(member)
6566
: null;
6667

6768
if (name == null)
6869
throw new ArgumentException("Could not resolve a name from the given Expression or MemberInfo.");
6970

7071
return name;
7172
}
72-
73-
private string ResolveToLastToken(Expression expression, MemberInfo member)
74-
{
75-
var name = expression != null
76-
? this.ResolveToLastToken(expression)
77-
: member != null
78-
? this.Resolve(member)
79-
: null;
80-
81-
if (name == null)
82-
throw new ArgumentException("Could not resolve a name from the given Expression or MemberInfo.");
83-
84-
return name;
85-
}
86-
87-
private string Resolve(MemberInfo info)
88-
{
89-
if (info == null)
90-
return null;
91-
92-
var name = info.Name;
93-
94-
IPropertyMapping propertyMapping = null;
95-
if (this._settings.PropertyMappings.TryGetValue(info, out propertyMapping))
96-
return propertyMapping.Name;
97-
98-
var att = ElasticsearchPropertyAttribute.From(info);
99-
if (att != null && !att.Name.IsNullOrEmpty())
100-
return att.Name;
101-
102-
return _settings.Serializer?.CreatePropertyName(info) ?? _settings.DefaultFieldNameInferrer(name);
103-
}
104-
105-
private string Resolve(Expression expression)
106-
{
107-
Stack = new Stack<string>();
108-
Visit(expression);
109-
return Stack
110-
.Aggregate(
111-
new StringBuilder(),
112-
(sb, name) =>
113-
(sb.Length > 0 ? sb.Append(".") : sb).Append(name))
114-
.ToString();
115-
}
116-
117-
private string ResolveToLastToken(Expression expression)
118-
{
119-
Stack = new Stack<string>();
120-
Visit(expression);
121-
return Stack.Last();
122-
}
123-
124-
protected override Expression VisitMember(MemberExpression expression)
125-
{
126-
if (Stack == null) return base.VisitMember(expression);
127-
var resolvedName = this.Resolve(expression.Member);
128-
Stack.Push(resolvedName);
129-
return base.VisitMember(expression);
130-
}
131-
132-
protected override Expression VisitMethodCall(MethodCallExpression methodCall)
133-
{
134-
if (methodCall.Method.Name == "Suffix" && methodCall.Arguments.Any())
135-
{
136-
VisitConstantOrVariable(methodCall, Stack);
137-
var callingMember = new ReadOnlyCollection<Expression>(
138-
new List<Expression> { { methodCall.Arguments.First() } }
139-
);
140-
base.Visit(callingMember);
141-
return methodCall;
142-
}
143-
else if (methodCall.Method.Name == "get_Item" && methodCall.Arguments.Any())
144-
{
145-
var t = methodCall.Object.Type;
146-
var isDict =
147-
typeof(IDictionary).IsAssignableFrom(t)
148-
|| typeof(IDictionary<,>).IsAssignableFrom(t)
149-
|| (t.IsGeneric() && t.GetGenericTypeDefinition() == typeof(IDictionary<,>));
150-
151-
if (!isDict)
152-
{
153-
return base.VisitMethodCall(methodCall);
154-
}
155-
VisitConstantOrVariable(methodCall, Stack);
156-
Visit(methodCall.Object);
157-
return methodCall;
158-
}
159-
else if (IsLinqOperator(methodCall.Method))
160-
{
161-
for (int i = 1; i < methodCall.Arguments.Count; i++)
162-
{
163-
Visit(methodCall.Arguments[i]);
164-
}
165-
Visit(methodCall.Arguments[0]);
166-
return methodCall;
167-
}
168-
return base.VisitMethodCall(methodCall);
169-
}
170-
171-
private static void VisitConstantOrVariable(MethodCallExpression methodCall, Stack<string> stack)
172-
{
173-
var lastArg = methodCall.Arguments.Last();
174-
var constantExpression = lastArg as ConstantExpression;
175-
var value = constantExpression != null
176-
? constantExpression.Value.ToString()
177-
: Expression.Lambda(lastArg).Compile().DynamicInvoke().ToString();
178-
stack.Push(value);
179-
}
180-
181-
private static bool IsLinqOperator(MethodInfo methodInfo)
182-
{
183-
if (methodInfo.DeclaringType != typeof(Queryable) && methodInfo.DeclaringType != typeof(Enumerable))
184-
return false;
185-
186-
return methodInfo.GetCustomAttribute<ExtensionAttribute>() != null;
187-
}
18873
}
18974
}

0 commit comments

Comments
 (0)