Skip to content

Commit 9bdc742

Browse files
yonguelinkIsaac Ouellet-Therrien
and
Isaac Ouellet-Therrien
authored
Handle UseParameterizedNamesInDynamicQuery when parsing dynamic OfType function (#723)
* Test UseParameterizedNamesInDynamicQuery TypeOf use-case This test fails * Handle case where expression is MemberExpression This fixes #722 * Check TryUnwrapAsConstantExpression output before calling resolve --------- Co-authored-by: Isaac Ouellet-Therrien <[email protected]>
1 parent 7b94ef5 commit 9bdc742

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed

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

+22-9
Original file line numberDiff line numberDiff line change
@@ -2006,23 +2006,36 @@ private Expression ParseEnumerable(Expression instance, Type elementType, string
20062006
private Type ResolveTypeFromArgumentExpression(string functionName, Expression argumentExpression, int? arguments = null)
20072007
{
20082008
string argument = arguments == null ? string.Empty : arguments == 1 ? "first " : "second ";
2009+
20092010
switch (argumentExpression)
20102011
{
20112012
case ConstantExpression constantExpression:
2012-
switch (constantExpression.Value)
2013+
return ResolveTypeFromExpressionValue(functionName, constantExpression, argument);
2014+
2015+
case MemberExpression memberExpression:
2016+
if (_expressionHelper.TryUnwrapAsConstantExpression(memberExpression, out var unwrappedConstantExpression))
20132017
{
2014-
case string typeName:
2015-
return ResolveTypeStringFromArgument(typeName);
2018+
return ResolveTypeFromExpressionValue(functionName, unwrappedConstantExpression, argument);
2019+
}
20162020

2017-
case Type type:
2018-
return type;
2021+
break;
2022+
}
20192023

2020-
default:
2021-
throw ParseError(_textParser.CurrentToken.Pos, Res.FunctionRequiresNotNullArgOfType, functionName, argument, "string or System.Type");
2022-
}
2024+
throw ParseError(_textParser.CurrentToken.Pos, Res.FunctionRequiresNotNullArgOfType, functionName, argument, "ConstantExpression");
2025+
}
2026+
2027+
private Type ResolveTypeFromExpressionValue(string functionName, ConstantExpression constantExpression, string argument)
2028+
{
2029+
switch (constantExpression.Value)
2030+
{
2031+
case string typeName:
2032+
return ResolveTypeStringFromArgument(typeName);
2033+
2034+
case Type type:
2035+
return type;
20232036

20242037
default:
2025-
throw ParseError(_textParser.CurrentToken.Pos, Res.FunctionRequiresNotNullArgOfType, functionName, argument, "ConstantExpression");
2038+
throw ParseError(_textParser.CurrentToken.Pos, Res.FunctionRequiresNotNullArgOfType, functionName, argument, "string or System.Type");
20262039
}
20272040
}
20282041

test/System.Linq.Dynamic.Core.Tests/QueryableTests.Is,OfType,As,Cast.cs

+30
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,36 @@ public void OfType_Dynamic_WithFullName()
6666
Check.That(oftypeDynamic.Length).Equals(oftype.Length);
6767
}
6868

69+
[Theory]
70+
[InlineData(true)]
71+
[InlineData(false)]
72+
public void OfType_Dynamic_WithFullName_UseParameterizedNamesInDynamicQuery(bool useParameterizedNamesInDynamicQuery)
73+
{
74+
// Assign
75+
var qry = new[]
76+
{
77+
new CompanyWithBaseEmployees
78+
{
79+
Employees = new BaseEmployee[]
80+
{
81+
new Worker { Name = "e" }, new Boss { Name = "e" }
82+
}
83+
}
84+
}.AsQueryable();
85+
86+
var parsingConfig = new ParsingConfig
87+
{
88+
UseParameterizedNamesInDynamicQuery = useParameterizedNamesInDynamicQuery
89+
};
90+
91+
// Act
92+
var oftype = qry.Select(c => c.Employees.OfType<Worker>().Where(e => e.Name == "e")).ToArray();
93+
var oftypeDynamic = qry.Select(parsingConfig, "Employees.OfType(\"System.Linq.Dynamic.Core.Tests.Entities.Worker\").Where(Name == \"e\")").ToDynamicArray();
94+
95+
// Assert
96+
Check.That(oftypeDynamic.Length).Equals(oftype.Length);
97+
}
98+
6999
internal class Base { }
70100

71101
internal class DerivedA : Base { }

0 commit comments

Comments
 (0)