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
67 changes: 49 additions & 18 deletions src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
ParameterExpression parameter = ParameterExpressionHelper.CreateParameterExpression(source.ElementType, "s");
Expression selector = Expression.Lambda(Expression.MakeMemberAccess(parameter, property), parameter);
// We've tried to find an expression of the type Expression<Func<TSource, TAcc>>,
// which is expressed as ( (TSource s) => s.Price );

Check warning on line 69 in src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs

View workflow job for this annotation

GitHub Actions / Linux: Build and Tests

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

var methods = typeof(Queryable).GetMethods().Where(x => x.Name == function && x.IsGenericMethod).ToArray();

Expand Down Expand Up @@ -125,6 +125,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -176,6 +177,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -246,6 +248,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -399,6 +402,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -529,6 +533,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -601,6 +606,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -679,8 +685,9 @@
{
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(keySelector, nameof(keySelector));
Check.NotEmpty(resultSelector, nameof(resultSelector));
Check.NotEmpty(keySelector);
Check.NotEmpty(resultSelector);
Check.Args(args);

bool createParameterCtor = config.EvaluateGroupByAtDatabase || SupportsLinqToObjects(config, source);
LambdaExpression keyLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, keySelector, args);
Expand Down Expand Up @@ -807,7 +814,8 @@
{
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(keySelector, nameof(keySelector));
Check.NotEmpty(keySelector);
Check.Args(args);

bool createParameterCtor = config.EvaluateGroupByAtDatabase || SupportsLinqToObjects(config, source);
LambdaExpression keyLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, keySelector, args);
Expand Down Expand Up @@ -932,12 +940,13 @@
/// <returns>An <see cref="IQueryable"/> obtained by performing a grouped join on two sequences.</returns>
public static IQueryable GroupJoin(this IQueryable outer, ParsingConfig config, IEnumerable inner, string outerKeySelector, string innerKeySelector, string resultSelector, params object?[] args)
{
Check.NotNull(outer, nameof(outer));
Check.NotNull(outer);
Check.NotNull(config);
Check.NotNull(inner, nameof(inner));
Check.NotEmpty(outerKeySelector, nameof(outerKeySelector));
Check.NotEmpty(innerKeySelector, nameof(innerKeySelector));
Check.NotEmpty(resultSelector, nameof(resultSelector));
Check.NotNull(inner);
Check.NotEmpty(outerKeySelector);
Check.NotEmpty(innerKeySelector);
Check.NotEmpty(resultSelector);
Check.Args(args);

Type outerType = outer.ElementType;
Type innerType = inner.AsQueryable().ElementType;
Expand Down Expand Up @@ -989,12 +998,13 @@
{
//http://stackoverflow.com/questions/389094/how-to-create-a-dynamic-linq-join-extension-method

Check.NotNull(outer, nameof(outer));
Check.NotNull(outer);
Check.NotNull(config);
Check.NotNull(inner, nameof(inner));
Check.NotEmpty(outerKeySelector, nameof(outerKeySelector));
Check.NotEmpty(innerKeySelector, nameof(innerKeySelector));
Check.NotEmpty(resultSelector, nameof(resultSelector));
Check.NotNull(inner);
Check.NotEmpty(outerKeySelector);
Check.NotEmpty(innerKeySelector);
Check.NotEmpty(resultSelector);
Check.Args(args);

Type outerType = outer.ElementType;
Type innerType = inner.AsQueryable().ElementType;
Expand Down Expand Up @@ -1094,6 +1104,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -1166,6 +1177,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -1244,6 +1256,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -1316,6 +1329,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, typeof(object), predicate, args);
Expand Down Expand Up @@ -1388,6 +1402,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, typeof(object), predicate, args);
Expand Down Expand Up @@ -1545,6 +1560,8 @@
/// </example>
public static IOrderedQueryable OrderBy(this IQueryable source, ParsingConfig config, string ordering, params object?[] args)
{
Check.Args(args);

if (args.Length > 0 && args[0] != null && args[0]!.GetType().GetInterfaces().Any(i => i.Name.Contains("IComparer`1")))
{
return InternalOrderBy(source, config, ordering, args[0]!, args);
Expand Down Expand Up @@ -1584,6 +1601,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(ordering);
Check.Args(args);

ParameterExpression[] parameters = [ParameterExpressionHelper.CreateParameterExpression(source.ElementType, string.Empty, config.RenameEmptyParameterExpressionNames)];
var parser = new ExpressionParser(parameters, ordering, args, config, true);
Expand Down Expand Up @@ -1758,6 +1776,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(selector);
Check.Args(args);

bool createParameterCtor = config.EvaluateGroupByAtDatabase || SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, selector, args);
Expand Down Expand Up @@ -1799,6 +1818,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(selector);
Check.Args(args);

bool createParameterCtor = config.EvaluateGroupByAtDatabase || SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, typeof(TResult), selector, args);
Expand Down Expand Up @@ -1841,8 +1861,9 @@
{
Check.NotNull(source);
Check.NotNull(config);
Check.NotNull(resultType, nameof(resultType));
Check.NotNull(resultType);
Check.NotEmpty(selector);
Check.Args(args);

bool createParameterCtor = config.EvaluateGroupByAtDatabase || SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, resultType, selector, args);
Expand Down Expand Up @@ -1907,6 +1928,7 @@
Check.NotNull(config);
Check.NotNull(resultType);
Check.NotEmpty(selector);
Check.Args(args);

return SelectManyInternal(source, config, resultType, selector, args);
}
Expand Down Expand Up @@ -1978,6 +2000,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(selector);
Check.Args(args);

bool createParameterCtor = config.EvaluateGroupByAtDatabase || SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, selector, args);
Expand Down Expand Up @@ -2076,10 +2099,12 @@
{
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(collectionSelector, nameof(collectionSelector));
Check.NotEmpty(collectionParameterName, nameof(collectionParameterName));
Check.NotEmpty(resultSelector, nameof(resultSelector));
Check.NotEmpty(resultParameterName, nameof(resultParameterName));
Check.NotEmpty(collectionSelector);
Check.NotEmpty(collectionParameterName);
Check.NotEmpty(resultSelector);
Check.NotEmpty(resultParameterName);
Check.Args(collectionSelectorArgs);
Check.Args(resultSelectorArgs);

bool createParameterCtor = config.EvaluateGroupByAtDatabase || SupportsLinqToObjects(config, source);
LambdaExpression sourceSelectLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, collectionSelector, collectionSelectorArgs);
Expand Down Expand Up @@ -2111,7 +2136,7 @@
/// <inheritdoc cref="SelectMany(IQueryable, ParsingConfig, string, string, string, string, object[], object[])"/>
public static IQueryable SelectMany(this IQueryable source, string collectionSelector, string resultSelector, string collectionParameterName, string resultParameterName, object?[]? collectionSelectorArgs = null, params object?[]? resultSelectorArgs)
{
return SelectMany(source, ParsingConfig.Default, collectionSelector, resultSelector, collectionParameterName, resultParameterName, collectionSelectorArgs, resultSelectorArgs);

Check warning on line 2139 in src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs

View workflow job for this annotation

GitHub Actions / Linux: Build and Tests

Argument of type 'object?[]' cannot be used for parameter 'resultSelectorArgs' of type 'object[]' in 'IQueryable DynamicQueryableExtensions.SelectMany(IQueryable source, ParsingConfig config, string collectionSelector, string resultSelector, string collectionParameterName, string resultParameterName, object?[]? collectionSelectorArgs = null, params object[]? resultSelectorArgs)' due to differences in the nullability of reference types.

Check warning on line 2139 in src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs

View workflow job for this annotation

GitHub Actions / Linux: Build and Tests

Argument of type 'object?[]' cannot be used for parameter 'resultSelectorArgs' of type 'object[]' in 'IQueryable DynamicQueryableExtensions.SelectMany(IQueryable source, ParsingConfig config, string collectionSelector, string resultSelector, string collectionParameterName, string resultParameterName, object?[]? collectionSelectorArgs = null, params object[]? resultSelectorArgs)' due to differences in the nullability of reference types.

Check warning on line 2139 in src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs

View workflow job for this annotation

GitHub Actions / Windows: Build and Tests

Argument of type 'object?[]' cannot be used for parameter 'resultSelectorArgs' of type 'object[]' in 'IQueryable DynamicQueryableExtensions.SelectMany(IQueryable source, ParsingConfig config, string collectionSelector, string resultSelector, string collectionParameterName, string resultParameterName, object?[]? collectionSelectorArgs = null, params object[]? resultSelectorArgs)' due to differences in the nullability of reference types.

Check warning on line 2139 in src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs

View workflow job for this annotation

GitHub Actions / Windows: Build and Tests

Argument of type 'object?[]' cannot be used for parameter 'resultSelectorArgs' of type 'object[]' in 'IQueryable DynamicQueryableExtensions.SelectMany(IQueryable source, ParsingConfig config, string collectionSelector, string resultSelector, string collectionParameterName, string resultParameterName, object?[]? collectionSelectorArgs = null, params object[]? resultSelectorArgs)' due to differences in the nullability of reference types.

Check warning on line 2139 in src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs

View workflow job for this annotation

GitHub Actions / Linux: Build and Tests

Argument of type 'object?[]' cannot be used for parameter 'resultSelectorArgs' of type 'object[]' in 'IQueryable DynamicQueryableExtensions.SelectMany(IQueryable source, ParsingConfig config, string collectionSelector, string resultSelector, string collectionParameterName, string resultParameterName, object?[]? collectionSelectorArgs = null, params object[]? resultSelectorArgs)' due to differences in the nullability of reference types.

Check warning on line 2139 in src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs

View workflow job for this annotation

GitHub Actions / Linux: Build and Tests

Argument of type 'object?[]' cannot be used for parameter 'resultSelectorArgs' of type 'object[]' in 'IQueryable DynamicQueryableExtensions.SelectMany(IQueryable source, ParsingConfig config, string collectionSelector, string resultSelector, string collectionParameterName, string resultParameterName, object?[]? collectionSelectorArgs = null, params object[]? resultSelectorArgs)' due to differences in the nullability of reference types.
}

#endregion SelectMany
Expand Down Expand Up @@ -2227,6 +2252,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -2309,6 +2335,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotNull(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -2365,6 +2392,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -2439,6 +2467,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotNull(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down Expand Up @@ -2553,6 +2582,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(ordering);
Check.Args(args);

ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(source.ElementType, string.Empty, config.RenameEmptyParameterExpressionNames) };
ExpressionParser parser = new ExpressionParser(parameters, ordering, args, config);
Expand Down Expand Up @@ -2649,6 +2679,7 @@
Check.NotNull(source);
Check.NotNull(config);
Check.NotEmpty(predicate);
Check.Args(args);

bool createParameterCtor = SupportsLinqToObjects(config, source);
LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args);
Expand Down
12 changes: 12 additions & 0 deletions src/System.Linq.Dynamic.Core/Validation/Check.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ namespace System.Linq.Dynamic.Core.Validation;
[DebuggerStepThrough]
internal static class Check
{
private const string ParsingConfigError = "The ParsingConfig should be provided as first argument to this method.";

public static object?[]? Args(object?[]? args, [CallerArgumentExpression("args")] string? parameterName = null)
{
if (args?.Any(a => a is ParsingConfig) == true)
{
throw new ArgumentException(ParsingConfigError, parameterName);
}

return args;
}

public static T Condition<T>(T value, Predicate<T> predicate, [CallerArgumentExpression("value")] string? parameterName = null)
{
NotNull(predicate);
Expand Down
4 changes: 2 additions & 2 deletions test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1281,8 +1281,8 @@ public void ExpressionTests_In_Enum()

// Act
var expected = qry.Where(x => new[] { TestEnum.Var1, TestEnum.Var2 }.Contains(x.TestEnum)).ToArray();
var result1 = qry.Where("it.TestEnum in (\"Var1\", \"Var2\")", config).ToArray();
var result2 = qry.Where("it.TestEnum in (0, 1)", config).ToArray();
var result1 = qry.Where(config, "it.TestEnum in (\"Var1\", \"Var2\")").ToArray();
var result2 = qry.Where(config, "it.TestEnum in (0, 1)").ToArray();

// Assert
Check.That(result1).ContainsExactly(expected);
Expand Down
2 changes: 2 additions & 0 deletions test/System.Linq.Dynamic.Core.Tests/QueryableTests.Where.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ public void Where_Dynamic_Exceptions()
Assert.Throws<ArgumentNullException>(() => qry.Where((string?)null));
Assert.Throws<ArgumentException>(() => qry.Where(""));
Assert.Throws<ArgumentException>(() => qry.Where(" "));
var parsingConfigException = Assert.Throws<ArgumentException>(() => qry.Where("UserName == \"x\"", ParsingConfig.Default));
Assert.Equal("The ParsingConfig should be provided as first argument to this method. (Parameter 'args')", parsingConfigException.Message);
}

[Fact]
Expand Down
Loading