Skip to content

Commit

Permalink
Handle UseParameterizedNamesInDynamicQuery when parsing dynamic OfTyp…
Browse files Browse the repository at this point in the history
…e 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 <iotherrien@dns1.sherweb.com>
  • Loading branch information
yonguelink and Isaac Ouellet-Therrien committed Jul 15, 2023
1 parent 7b94ef5 commit 9bdc742
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 9 deletions.
31 changes: 22 additions & 9 deletions src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2006,23 +2006,36 @@ private Expression ParseEnumerable(Expression instance, Type elementType, string
private Type ResolveTypeFromArgumentExpression(string functionName, Expression argumentExpression, int? arguments = null)
{
string argument = arguments == null ? string.Empty : arguments == 1 ? "first " : "second ";

switch (argumentExpression)
{
case ConstantExpression constantExpression:
switch (constantExpression.Value)
return ResolveTypeFromExpressionValue(functionName, constantExpression, argument);

case MemberExpression memberExpression:
if (_expressionHelper.TryUnwrapAsConstantExpression(memberExpression, out var unwrappedConstantExpression))
{
case string typeName:
return ResolveTypeStringFromArgument(typeName);
return ResolveTypeFromExpressionValue(functionName, unwrappedConstantExpression, argument);
}

case Type type:
return type;
break;
}

default:
throw ParseError(_textParser.CurrentToken.Pos, Res.FunctionRequiresNotNullArgOfType, functionName, argument, "string or System.Type");
}
throw ParseError(_textParser.CurrentToken.Pos, Res.FunctionRequiresNotNullArgOfType, functionName, argument, "ConstantExpression");
}

private Type ResolveTypeFromExpressionValue(string functionName, ConstantExpression constantExpression, string argument)
{
switch (constantExpression.Value)
{
case string typeName:
return ResolveTypeStringFromArgument(typeName);

case Type type:
return type;

default:
throw ParseError(_textParser.CurrentToken.Pos, Res.FunctionRequiresNotNullArgOfType, functionName, argument, "ConstantExpression");
throw ParseError(_textParser.CurrentToken.Pos, Res.FunctionRequiresNotNullArgOfType, functionName, argument, "string or System.Type");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,36 @@ public void OfType_Dynamic_WithFullName()
Check.That(oftypeDynamic.Length).Equals(oftype.Length);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void OfType_Dynamic_WithFullName_UseParameterizedNamesInDynamicQuery(bool useParameterizedNamesInDynamicQuery)
{
// Assign
var qry = new[]
{
new CompanyWithBaseEmployees
{
Employees = new BaseEmployee[]
{
new Worker { Name = "e" }, new Boss { Name = "e" }
}
}
}.AsQueryable();

var parsingConfig = new ParsingConfig
{
UseParameterizedNamesInDynamicQuery = useParameterizedNamesInDynamicQuery
};

// Act
var oftype = qry.Select(c => c.Employees.OfType<Worker>().Where(e => e.Name == "e")).ToArray();
var oftypeDynamic = qry.Select(parsingConfig, "Employees.OfType(\"System.Linq.Dynamic.Core.Tests.Entities.Worker\").Where(Name == \"e\")").ToDynamicArray();

// Assert
Check.That(oftypeDynamic.Length).Equals(oftype.Length);
}

internal class Base { }

internal class DerivedA : Base { }
Expand Down

0 comments on commit 9bdc742

Please sign in to comment.