Skip to content

Commit 2689483

Browse files
committed
1 parent 3da1e48 commit 2689483

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs

+24-8
Original file line numberDiff line numberDiff line change
@@ -1795,19 +1795,25 @@ private Expression ParseMemberAccess(Type? type, Expression? expression, string?
17951795

17961796
if (_textParser.CurrentToken.Id == TokenId.OpenParen)
17971797
{
1798+
Expression[]? args = null;
1799+
17981800
var isStaticAccess = expression == null;
17991801

1800-
if (!isStaticAccess && type != typeof(string))
1802+
if (!isStaticAccess)
18011803
{
18021804
var enumerableType = TypeHelper.FindGenericType(typeof(IEnumerable<>), type);
18031805
if (enumerableType != null)
18041806
{
1805-
Type elementType = enumerableType.GetTypeInfo().GetGenericTypeArguments()[0];
1806-
return ParseEnumerable(expression!, elementType, id, errorPos, type);
1807+
var elementType = enumerableType.GetTypeInfo().GetGenericTypeArguments()[0];
1808+
if (TryParseEnumerable(expression!, elementType, id, errorPos, type, out args, out var enumerableExpression))
1809+
{
1810+
return enumerableExpression;
1811+
}
18071812
}
18081813
}
18091814

1810-
Expression[] args = ParseArgumentList();
1815+
// If args is not set by TryParseEnumerable (in case when the expression is not an Enumerable), do parse the argument list here.
1816+
args ??= ParseArgumentList();
18111817
switch (_methodFinder.FindMethod(type, id, isStaticAccess, ref expression, ref args, out var methodBase))
18121818
{
18131819
case 0:
@@ -2038,7 +2044,7 @@ private Expression ParseAsEnumOrNestedClass(string id)
20382044
return ParseMemberAccess(type, null, identifier);
20392045
}
20402046

2041-
private Expression ParseEnumerable(Expression instance, Type elementType, string methodName, int errorPos, Type? type)
2047+
private bool TryParseEnumerable(Expression instance, Type elementType, string methodName, int errorPos, Type? type, out Expression[]? args, [NotNullWhen(true)] out Expression? expression)
20422048
{
20432049
var oldParent = _parent;
20442050

@@ -2057,15 +2063,24 @@ private Expression ParseEnumerable(Expression instance, Type elementType, string
20572063
_it = innerIt;
20582064
}
20592065

2060-
Expression[] args = ParseArgumentList();
2066+
args = ParseArgumentList();
2067+
2068+
var t = type ?? instance.Type;
2069+
if (t == typeof(string) && _methodFinder.ContainsMethod(t, methodName, false, instance, ref args))
2070+
{
2071+
// In case the type is a string, and does contain the methodName (like "IndexOf"), then return false to indicate that the methodName is not an Enumerable method.
2072+
expression = null;
2073+
return false;
2074+
}
20612075

20622076
_it = outerIt;
20632077
_parent = oldParent;
20642078

20652079
if (type != null && TypeHelper.IsDictionary(type) && _methodFinder.ContainsMethod(type, methodName, false))
20662080
{
20672081
var dictionaryMethod = type.GetMethod(methodName)!;
2068-
return Expression.Call(instance, dictionaryMethod, args);
2082+
expression = Expression.Call(instance, dictionaryMethod, args);
2083+
return true;
20692084
}
20702085

20712086
// #794 - Check if the method is an aggregate (Average or Sum) method and try to update the arguments to match the method arguments
@@ -2139,7 +2154,8 @@ private Expression ParseEnumerable(Expression instance, Type elementType, string
21392154
}
21402155
}
21412156

2142-
return Expression.Call(callType, methodName, typeArgs, args);
2157+
expression = Expression.Call(callType, methodName, typeArgs, args);
2158+
return true;
21432159
}
21442160

21452161
private Type ResolveTypeFromArgumentExpression(string functionName, Expression argumentExpression, int? arguments = null)

0 commit comments

Comments
 (0)