Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions src/System.Linq.Dynamic.Core/ExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ interface IEnumerableSignatures
void Distinct();
void First(bool predicate);
void FirstOrDefault(bool predicate);
void GroupBy(object selector);
void GroupBy(object keySelector);
void GroupBy(object keySelector, object elementSelector);
void Last(bool predicate);
void LastOrDefault(bool predicate);
void Max(object selector);
Expand Down Expand Up @@ -181,6 +182,7 @@ interface IEnumerableSignatures
void LastOrDefault();
void Single();
void SingleOrDefault();
void ToList();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a test to cover this method?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes in ParseLambdaComplex_2

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And a function like ToArray, can that also be defined?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think so, but I've not tested/used

}

// These shorthands have different name than actual type and therefore not recognized by default from the _predefinedTypes
Expand Down Expand Up @@ -1641,7 +1643,14 @@ Expression ParseAggregate(Expression instance, Type elementType, string methodNa
Type[] typeArgs;
if (new[] { "Min", "Max", "Select", "OrderBy", "OrderByDescending", "ThenBy", "ThenByDescending", "GroupBy" }.Contains(signature.Name))
{
typeArgs = new[] { elementType, args[0].Type };
if (args.Length == 2)
{
typeArgs = new[] { elementType, args[0].Type, args[1].Type };
}
else
{
typeArgs = new[] { elementType, args[0].Type };
}
}
else if (signature.Name == "SelectMany")
{
Expand All @@ -1668,7 +1677,14 @@ Expression ParseAggregate(Expression instance, Type elementType, string methodNa
}
else
{
args = new[] { instance, Expression.Lambda(args[0], innerIt) };
if (args.Length == 2)
{
args = new[] { instance, Expression.Lambda(args[0], innerIt), Expression.Lambda(args[1], innerIt) };
}
else
{
args = new[] {instance, Expression.Lambda(args[0], innerIt)};
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,48 @@ public void ParseLambda_EmptyParameterList()
Check.That(result).Equals(3);
}

[Fact]
public void ParseLambdaComplex_1()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to move this test to the file QueryableTests.GroupBy.cs or does that not fit?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other tests in this class (for example ParseLambda_1) also test Lambda with GroupBy

{
// Arrange
var testList = User.GenerateSampleModels(51);
var qry = testList.AsQueryable();

// Act
string query = "GroupBy(x => new { x.Profile.Age }, it).OrderBy(gg => gg.Key.Age).Select(j => new (j.Key.Age, j.Sum(k => k.Income) As TotalIncome))";
LambdaExpression expression = DynamicExpressionParser.ParseLambda(qry.GetType(), null, query);
Delegate del = expression.Compile();
IEnumerable<dynamic> result = del.DynamicInvoke(qry) as IEnumerable<dynamic>;

var expected = qry.GroupBy(x => new { x.Profile.Age }, x => x).OrderBy(gg => gg.Key.Age).Select(j => new { j.Key.Age, TotalIncome = j.Sum(k => k.Income) }).Select(c => new ComplexParseLambda1Result { Age = c.Age, TotalIncome = c.TotalIncome }).Cast<dynamic>().ToArray();

// Assert
Check.That(result).IsNotNull();
Check.That(result).HasSize(expected.Length);
Check.That(result.ToArray()[0]).Equals(expected[0]);
}

[Fact]
public void ParseLambdaComplex_2()
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tests ToList()

{
// Arrange
var testList = User.GenerateSampleModels(51);
var qry = testList.AsQueryable();

// Act
string query = "OrderBy(gg => gg.Income).ToList()";
LambdaExpression expression = DynamicExpressionParser.ParseLambda(qry.GetType(), null, query);
Delegate del = expression.Compile();
IEnumerable<dynamic> result = del.DynamicInvoke(qry) as IEnumerable<dynamic>;

var expected = qry.OrderBy(gg => gg.Income).ToList();

// Assert
Check.That(result).IsNotNull();
Check.That(result).HasSize(expected.Count);
Check.That(result.ToArray()[0]).Equals(expected[0]);
}

[Fact]
public void ParseLambda_1()
{
Expand Down Expand Up @@ -306,4 +348,4 @@ public void ParseLambda_IllegalMethodCall_ThrowsException()
.Throws<ParseException>().WithMessage("Methods on type 'Stream' are not accessible");
}
}
}
}