diff --git a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
index add203e1..dad76ebd 100644
--- a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
+++ b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
@@ -857,9 +857,12 @@ private Expression ParseIdentifier()
{
_textParser.ValidateToken(TokenId.Identifier);
- if (_keywordsHelper.TryGetValue(_textParser.CurrentToken.Text, out object? value) &&
- // Prioritize property or field over the type
- !(value is Type && _it != null && FindPropertyOrField(_it.Type, _textParser.CurrentToken.Text, false) != null))
+ var isValidKeyWord = _keywordsHelper.TryGetValue(_textParser.CurrentToken.Text, out var value);
+
+ var extraCondition = !_parsingConfig.PrioritizePropertyOrFieldOverTheType ||
+ (_parsingConfig.PrioritizePropertyOrFieldOverTheType && !(value is Type && _it != null && FindPropertyOrField(_it.Type, _textParser.CurrentToken.Text, false) != null));
+
+ if (isValidKeyWord && extraCondition)
{
if (value is Type typeValue)
{
@@ -1711,9 +1714,13 @@ private Expression ParseMemberAccess(Type? type, Expression? expression)
return Expression.Field(expression, field);
}
- if (!_parsingConfig.DisableMemberAccessToIndexAccessorFallback && expression != null)
+ // #357 #662
+ var extraCheck = !_parsingConfig.PrioritizePropertyOrFieldOverTheType ||
+ _parsingConfig.PrioritizePropertyOrFieldOverTheType && expression != null;
+
+ if (!_parsingConfig.DisableMemberAccessToIndexAccessorFallback && extraCheck)
{
- var indexerMethod = expression.Type.GetMethod("get_Item", new[] { typeof(string) });
+ var indexerMethod = expression?.Type.GetMethod("get_Item", new[] { typeof(string) });
if (indexerMethod != null)
{
return Expression.Call(expression, indexerMethod, Expression.Constant(id));
@@ -2139,11 +2146,12 @@ private static Exception IncompatibleOperandsError(string opName, Expression lef
private MemberInfo? FindPropertyOrField(Type type, string memberName, bool staticAccess)
{
#if !(NETFX_CORE || WINDOWS_APP || UAP10_0 || NETSTANDARD)
- BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly | (staticAccess ? BindingFlags.Static : BindingFlags.Instance);
+ var extraBindingFlag = _parsingConfig.PrioritizePropertyOrFieldOverTheType && staticAccess ? BindingFlags.Static : BindingFlags.Instance;
+ var bindingFlags = BindingFlags.Public | BindingFlags.DeclaredOnly | extraBindingFlag;
foreach (Type t in TypeHelper.GetSelfAndBaseTypes(type))
{
var findMembersType = _parsingConfig?.IsCaseSensitive == true ? Type.FilterName : Type.FilterNameIgnoreCase;
- var members = t.FindMembers(MemberTypes.Property | MemberTypes.Field, flags, findMembersType, memberName);
+ var members = t.FindMembers(MemberTypes.Property | MemberTypes.Field, bindingFlags, findMembersType, memberName);
if (members.Length != 0)
{
diff --git a/src/System.Linq.Dynamic.Core/ParsingConfig.cs b/src/System.Linq.Dynamic.Core/ParsingConfig.cs
index aa4c1a6d..66f41fab 100644
--- a/src/System.Linq.Dynamic.Core/ParsingConfig.cs
+++ b/src/System.Linq.Dynamic.Core/ParsingConfig.cs
@@ -211,5 +211,14 @@ public IQueryableAnalyzer QueryableAnalyzer
/// Default value is true.
///
public bool SupportCastingToFullyQualifiedTypeAsString { get; set; } = true;
+
+ ///
+ /// When the type and property have the same name the parser takes the property instead of type when this setting is set to true.
+ ///
+ /// The value from this setting should also be set to true when ExtensionMethods are used.
+ ///
+ /// Default value is false.
+ ///
+ public bool PrioritizePropertyOrFieldOverTheType { get; set; }
}
}
\ No newline at end of file
diff --git a/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs b/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs
index 297768d8..3bd1332c 100644
--- a/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs
@@ -1449,9 +1449,10 @@ public void DynamicExpressionParser_ParseLambda_GenericExtensionMethod()
{
// Arrange
var testList = User.GenerateSampleModels(51);
- var config = new ParsingConfig()
+ var config = new ParsingConfig
{
- CustomTypeProvider = new DefaultDynamicLinqCustomTypeProviderForGenericExtensionMethod()
+ CustomTypeProvider = new DefaultDynamicLinqCustomTypeProviderForGenericExtensionMethod(),
+ PrioritizePropertyOrFieldOverTheType = true
};
// Act
@@ -1461,7 +1462,6 @@ public void DynamicExpressionParser_ParseLambda_GenericExtensionMethod()
var result = Enumerable.Where(testList, del);
-
var expected = testList.Where(x => new string[] { "User4", "User2" }.Contains(x.UserName)).ToList();
// Assert
diff --git a/test/System.Linq.Dynamic.Core.Tests/Entities/Company.cs b/test/System.Linq.Dynamic.Core.Tests/Entities/Company.cs
index a6a6e5c3..459dbca8 100644
--- a/test/System.Linq.Dynamic.Core.Tests/Entities/Company.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/Entities/Company.cs
@@ -1,15 +1,16 @@
using System.Collections.Generic;
-namespace System.Linq.Dynamic.Core.Tests.Entities
+namespace System.Linq.Dynamic.Core.Tests.Entities;
+
+public class Company : Entity
{
- public class Company : Entity
- {
- public string Name { get; set; }
+ public string Name { get; set; }
+
+ public long? MainCompanyId { get; set; }
- public long? MainCompanyId { get; set; }
+ public MainCompany MainCompany { get; set; }
- public MainCompany MainCompany { get; set; }
+ public ICollection Employees { get; set; }
- public ICollection Employees { get; set; }
- }
+ public DateTime DateTime { get; set; }
}
\ No newline at end of file
diff --git a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
index f5537a6c..b9b8341a 100644
--- a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
@@ -290,6 +290,10 @@ public void ExpressionTests_Cast_To_Enum_Using_DynamicLinqType()
public void ExpressionTests_Cast_To_FullTypeDateTime_Using_DynamicLinqType()
{
// Arrange
+ var config = new ParsingConfig
+ {
+ PrioritizePropertyOrFieldOverTheType = true
+ };
var list = new List
{
new SimpleValuesModel { DateTime = DateTime.Now }
@@ -297,7 +301,7 @@ public void ExpressionTests_Cast_To_FullTypeDateTime_Using_DynamicLinqType()
// Act
var expectedResult = list.Select(x => x.DateTime);
- var result = list.AsQueryable().Select($"\"{typeof(DateTime).FullName}\"(DateTime)");
+ var result = list.AsQueryable().Select(config, $"\"{typeof(DateTime).FullName}\"(DateTime)");
// Assert
Assert.Equal(expectedResult.ToArray(), result.ToDynamicArray());
@@ -307,6 +311,10 @@ public void ExpressionTests_Cast_To_FullTypeDateTime_Using_DynamicLinqType()
public void ExpressionTests_Cast_To_FullTypeDateTimeNullable_Using_DynamicLinqType()
{
// Arrange
+ var config = new ParsingConfig
+ {
+ PrioritizePropertyOrFieldOverTheType = true
+ };
var list = new List
{
new SimpleValuesModel { DateTime = DateTime.Now }
@@ -314,7 +322,7 @@ public void ExpressionTests_Cast_To_FullTypeDateTimeNullable_Using_DynamicLinqTy
// Act
var expectedResult = list.Select(x => (DateTime?)x.DateTime);
- var result = list.AsQueryable().Select($"\"{typeof(DateTime).FullName}\"?(DateTime)");
+ var result = list.AsQueryable().Select(config, $"\"{typeof(DateTime).FullName}\"?(DateTime)");
// Assert
Assert.Equal(expectedResult.ToArray(), result.ToDynamicArray());
@@ -1502,7 +1510,8 @@ public void ExpressionTests_MethodCall_GenericExtension()
{
var config = new ParsingConfig
{
- CustomTypeProvider = new DefaultDynamicLinqCustomTypeProviderForStaticTesting()
+ CustomTypeProvider = new DefaultDynamicLinqCustomTypeProviderForStaticTesting(),
+ PrioritizePropertyOrFieldOverTheType = true
};
// Arrange
diff --git a/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.TypeAccess.cs b/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.TypeAccess.cs
index c5bed90c..d79ca134 100644
--- a/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.TypeAccess.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.TypeAccess.cs
@@ -53,6 +53,21 @@ public void ParseTypeAccess_Via_Constructor_String_To_DateTime_Valid()
expression.ToString().Should().NotBeEmpty();
}
+ [Fact]
+ public void ParseTypeAccess_Via_Constructor_Arguments_To_DateTime_Valid()
+ {
+ // Arrange
+ var arguments = "2022, 10, 31, 9, 15, 11";
+ var parameter = Expression.Parameter(typeof(DateTime));
+
+ // Act
+ var parser = new ExpressionParser(new[] { parameter }, $"DateTime({arguments})", new object[] { }, ParsingConfig.Default);
+ var expression = parser.Parse(typeof(DateTime));
+
+ // Assert
+ expression.ToString().Should().NotBeEmpty();
+ }
+
[Theory]
[InlineData(null)]
[InlineData("\"abc\"")]
diff --git a/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs b/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs
index 3015401a..b32c151c 100644
--- a/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs
@@ -1,224 +1,257 @@
-using FluentAssertions;
-using Moq;
-using NFluent;
-using System.Collections.Generic;
-using System.Globalization;
+using System.Collections.Generic;
using System.Linq.Dynamic.Core.CustomTypeProviders;
using System.Linq.Dynamic.Core.Exceptions;
using System.Linq.Dynamic.Core.Parser;
using System.Linq.Dynamic.Core.Tests.Entities;
using System.Linq.Expressions;
+using FluentAssertions;
+using Moq;
+using NFluent;
using Xunit;
-namespace System.Linq.Dynamic.Core.Tests.Parser
+namespace System.Linq.Dynamic.Core.Tests.Parser;
+
+public partial class ExpressionParserTests
{
- public partial class ExpressionParserTests
- {
- private readonly ParsingConfig _parsingConfig;
- private readonly Mock _dynamicTypeProviderMock;
+ private readonly Mock _dynamicTypeProviderMock;
- public ExpressionParserTests()
- {
- _dynamicTypeProviderMock = new Mock();
- _dynamicTypeProviderMock.Setup(dt => dt.GetCustomTypes()).Returns(new HashSet() { typeof(Company), typeof(MainCompany) });
- _dynamicTypeProviderMock.Setup(dt => dt.ResolveType(typeof(Company).FullName)).Returns(typeof(Company));
- _dynamicTypeProviderMock.Setup(dt => dt.ResolveType(typeof(MainCompany).FullName)).Returns(typeof(MainCompany));
- _dynamicTypeProviderMock.Setup(dt => dt.ResolveTypeBySimpleName("Company")).Returns(typeof(Company));
- _dynamicTypeProviderMock.Setup(dt => dt.ResolveTypeBySimpleName("MainCompany")).Returns(typeof(MainCompany));
-
- _parsingConfig = new ParsingConfig
- {
- CustomTypeProvider = _dynamicTypeProviderMock.Object
- };
- }
+ private readonly ParsingConfig _parsingConfig;
- [Fact]
- public void Parse_ParseBinaryInteger()
+ public ExpressionParserTests()
+ {
+ _dynamicTypeProviderMock = new Mock();
+ _dynamicTypeProviderMock.Setup(dt => dt.GetCustomTypes()).Returns(new HashSet() { typeof(Company), typeof(MainCompany) });
+ _dynamicTypeProviderMock.Setup(dt => dt.ResolveType(typeof(Company).FullName!)).Returns(typeof(Company));
+ _dynamicTypeProviderMock.Setup(dt => dt.ResolveType(typeof(MainCompany).FullName!)).Returns(typeof(MainCompany));
+ _dynamicTypeProviderMock.Setup(dt => dt.ResolveTypeBySimpleName("Company")).Returns(typeof(Company));
+ _dynamicTypeProviderMock.Setup(dt => dt.ResolveTypeBySimpleName("MainCompany")).Returns(typeof(MainCompany));
+
+ _parsingConfig = new ParsingConfig
{
- // Arrange
- var expression = "0b1100000011101";
- ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(int), "x") };
- var sut = new ExpressionParser(parameters, expression, null, null);
+ CustomTypeProvider = _dynamicTypeProviderMock.Object
+ };
+ }
- // Act
- var parsedExpression = sut.Parse(null).ToString();
+ [Fact]
+ public void Parse_ParseBinaryInteger()
+ {
+ // Arrange
+ var expression = "0b1100000011101";
+ ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(int), "x") };
+ var sut = new ExpressionParser(parameters, expression, null, null);
- // Assert
- parsedExpression.Should().Be("6173");
- }
+ // Act
+ var parsedExpression = sut.Parse(null).ToString();
- [Fact]
- public void Parse_ParseHexadecimalInteger()
- {
- // Arrange
- var expression = "0xFF";
- ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(int), "x") };
- var sut = new ExpressionParser(parameters, expression, null, null);
+ // Assert
+ parsedExpression.Should().Be("6173");
+ }
- // Act
- var parsedExpression = sut.Parse(null).ToString();
+ [Fact]
+ public void Parse_ParseHexadecimalInteger()
+ {
+ // Arrange
+ var expression = "0xFF";
+ ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(int), "x") };
+ var sut = new ExpressionParser(parameters, expression, null, null);
- // Assert
- parsedExpression.Should().Be("255");
- }
+ // Act
+ var parsedExpression = sut.Parse(null).ToString();
- [Theory]
- [InlineData("it == 1", "(x == 1)")]
- [InlineData("it eq 1", "(x == 1)")]
- [InlineData("it equal 1", "(x == 1)")]
- [InlineData("it != 1", "(x != 1)")]
- [InlineData("it ne 1", "(x != 1)")]
- [InlineData("it neq 1", "(x != 1)")]
- [InlineData("it notequal 1", "(x != 1)")]
- [InlineData("it lt 1", "(x < 1)")]
- [InlineData("it LessThan 1", "(x < 1)")]
- [InlineData("it le 1", "(x <= 1)")]
- [InlineData("it LessThanEqual 1", "(x <= 1)")]
- [InlineData("it gt 1", "(x > 1)")]
- [InlineData("it GreaterThan 1", "(x > 1)")]
- [InlineData("it ge 1", "(x >= 1)")]
- [InlineData("it GreaterThanEqual 1", "(x >= 1)")]
- public void Parse_ParseComparisonOperator(string expression, string result)
- {
- // Arrange
- ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(int), "x") };
- var sut = new ExpressionParser(parameters, expression, null, null);
+ // Assert
+ parsedExpression.Should().Be("255");
+ }
- // Act
- var parsedExpression = sut.Parse(null).ToString();
+ [Theory]
+ [InlineData("it == 1", "(x == 1)")]
+ [InlineData("it eq 1", "(x == 1)")]
+ [InlineData("it equal 1", "(x == 1)")]
+ [InlineData("it != 1", "(x != 1)")]
+ [InlineData("it ne 1", "(x != 1)")]
+ [InlineData("it neq 1", "(x != 1)")]
+ [InlineData("it notequal 1", "(x != 1)")]
+ [InlineData("it lt 1", "(x < 1)")]
+ [InlineData("it LessThan 1", "(x < 1)")]
+ [InlineData("it le 1", "(x <= 1)")]
+ [InlineData("it LessThanEqual 1", "(x <= 1)")]
+ [InlineData("it gt 1", "(x > 1)")]
+ [InlineData("it GreaterThan 1", "(x > 1)")]
+ [InlineData("it ge 1", "(x >= 1)")]
+ [InlineData("it GreaterThanEqual 1", "(x >= 1)")]
+ public void Parse_ParseComparisonOperator(string expression, string result)
+ {
+ // Arrange
+ ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(int), "x") };
+ var sut = new ExpressionParser(parameters, expression, null, null);
- // Assert
- Check.That(parsedExpression).Equals(result);
- }
+ // Act
+ var parsedExpression = sut.Parse(null).ToString();
- [Theory]
- [InlineData("it || true", "(x OrElse True)")]
- [InlineData("it or true", "(x OrElse True)")]
- [InlineData("it OrElse true", "(x OrElse True)")]
- public void Parse_ParseOrOperator(string expression, string result)
- {
- // Arrange
- ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(bool), "x") };
- var sut = new ExpressionParser(parameters, expression, null, null);
+ // Assert
+ Check.That(parsedExpression).Equals(result);
+ }
- // Act
- var parsedExpression = sut.Parse(null).ToString();
+ [Theory]
+ [InlineData("it || true", "(x OrElse True)")]
+ [InlineData("it or true", "(x OrElse True)")]
+ [InlineData("it OrElse true", "(x OrElse True)")]
+ public void Parse_ParseOrOperator(string expression, string result)
+ {
+ // Arrange
+ ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(bool), "x") };
+ var sut = new ExpressionParser(parameters, expression, null, null);
- // Assert
- Check.That(parsedExpression).Equals(result);
- }
+ // Act
+ var parsedExpression = sut.Parse(null).ToString();
- [Theory]
- [InlineData("it && true", "(x AndAlso True)")]
- [InlineData("it and true", "(x AndAlso True)")]
- [InlineData("it AndAlso true", "(x AndAlso True)")]
- public void Parse_ParseAndOperator(string expression, string result)
- {
- // Arrange
- ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(bool), "x") };
- var sut = new ExpressionParser(parameters, expression, null, null);
+ // Assert
+ Check.That(parsedExpression).Equals(result);
+ }
- // Act
- var parsedExpression = sut.Parse(null).ToString();
+ [Theory]
+ [InlineData("it && true", "(x AndAlso True)")]
+ [InlineData("it and true", "(x AndAlso True)")]
+ [InlineData("it AndAlso true", "(x AndAlso True)")]
+ public void Parse_ParseAndOperator(string expression, string result)
+ {
+ // Arrange
+ ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(bool), "x") };
+ var sut = new ExpressionParser(parameters, expression, null, null);
- // Assert
- Check.That(parsedExpression).Equals(result);
- }
+ // Act
+ var parsedExpression = sut.Parse(null).ToString();
- [Fact]
- public void Parse_ParseMultipleInOperators()
- {
- // Arrange
- ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(Company), "x") };
- var sut = new ExpressionParser(parameters, "MainCompanyId in (1, 2) and Name in (\"A\", \"B\")", null, null);
+ // Assert
+ Check.That(parsedExpression).Equals(result);
+ }
- // Act
- var parsedExpression = sut.Parse(null).ToString();
+ [Fact]
+ public void Parse_ParseMultipleInOperators()
+ {
+ // Arrange
+ ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(Company), "x") };
+ var sut = new ExpressionParser(parameters, "MainCompanyId in (1, 2) and Name in (\"A\", \"B\")", null, null);
- // Assert
- Check.That(parsedExpression).Equals("(((x.MainCompanyId == 1) OrElse (x.MainCompanyId == 2)) AndAlso ((x.Name == \"A\") OrElse (x.Name == \"B\")))");
- }
+ // Act
+ var parsedExpression = sut.Parse(null).ToString();
- [Fact]
- public void Parse_ParseInWrappedInParenthesis()
- {
- // Arrange
- ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(Company), "x") };
- var sut = new ExpressionParser(parameters, "(MainCompanyId in @0)", new object[] { new long?[] { 1, 2 } }, null);
+ // Assert
+ Check.That(parsedExpression).Equals("(((x.MainCompanyId == 1) OrElse (x.MainCompanyId == 2)) AndAlso ((x.Name == \"A\") OrElse (x.Name == \"B\")))");
+ }
- // Act
- var parsedExpression = sut.Parse(null).ToString();
+ [Fact]
+ public void Parse_ParseInWrappedInParenthesis()
+ {
+ // Arrange
+ ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(Company), "x") };
+ var sut = new ExpressionParser(parameters, "(MainCompanyId in @0)", new object[] { new long?[] { 1, 2 } }, null);
- // Assert
- Check.That(parsedExpression).Equals("value(System.Nullable`1[System.Int64][]).Contains(x.MainCompanyId)");
- }
+ // Act
+ var parsedExpression = sut.Parse(null).ToString();
- [Theory]
- [InlineData("string(\"\")", "")]
- [InlineData("string(\"a\")", "a")]
- [InlineData("int(42)", 42)]
- public void Parse_CastStringIntShouldReturnConstantExpression(string expression, object result)
- {
- // Arrange
- ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(bool), "x") };
- var sut = new ExpressionParser(parameters, expression, null, null);
+ // Assert
+ Check.That(parsedExpression).Equals("value(System.Nullable`1[System.Int64][]).Contains(x.MainCompanyId)");
+ }
- // Act
- var constantExpression = (ConstantExpression)sut.Parse(null);
+ [Theory]
+ [InlineData("string(\"\")", "")]
+ [InlineData("string(\"a\")", "a")]
+ [InlineData("int(42)", 42)]
+ public void Parse_CastStringIntShouldReturnConstantExpression(string expression, object result)
+ {
+ // Arrange
+ ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(bool), "x") };
+ var sut = new ExpressionParser(parameters, expression, null, null);
- // Assert
- Check.That(constantExpression.Value).Equals(result);
- }
+ // Act
+ var constantExpression = (ConstantExpression)sut.Parse(null);
+
+ // Assert
+ Check.That(constantExpression.Value).Equals(result);
+ }
- [Theory]
+ [Theory]
#if NET452
[InlineData("int?(5)", typeof(int?), "Convert(5)")]
[InlineData("int?(null)", typeof(int?), "Convert(null)")]
[InlineData("string(null)", typeof(string), "Convert(null)")]
#else
- [InlineData("int?(5)", typeof(int?), "Convert(5, Nullable`1)")]
- [InlineData("int?(null)", typeof(int?), "Convert(null, Nullable`1)")]
- [InlineData("string(null)", typeof(string), "Convert(null, String)")]
+ [InlineData("int?(5)", typeof(int?), "Convert(5, Nullable`1)")]
+ [InlineData("int?(null)", typeof(int?), "Convert(null, Nullable`1)")]
+ [InlineData("string(null)", typeof(string), "Convert(null, String)")]
#endif
- public void Parse_NullableShouldReturnNullable(string expression, object resultType, object result)
- {
- // Arrange
- ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(bool), "x") };
- var sut = new ExpressionParser(parameters, expression, null, null);
+ public void Parse_NullableShouldReturnNullable(string expression, object resultType, object result)
+ {
+ // Arrange
+ ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(bool), "x") };
+ var sut = new ExpressionParser(parameters, expression, null, null);
- // Act
- var unaryExpression = (UnaryExpression)sut.Parse(null);
+ // Act
+ var unaryExpression = (UnaryExpression)sut.Parse(null);
- // Assert
- Check.That(unaryExpression.Type).Equals(resultType);
- Check.That(unaryExpression.ToString()).Equals(result);
+ // Assert
+ Check.That(unaryExpression.Type).Equals(resultType);
+ Check.That(unaryExpression.ToString()).Equals(result);
+ }
+
+ [Theory]
+ [InlineData("it.MainCompany.Name != null", "(company.MainCompany.Name != null)")]
+ [InlineData("@MainCompany.Companies.Count() > 0", "(company.MainCompany.Companies.Count() > 0)")]
+ [InlineData("Company.Equals(null, null)", "Equals(null, null)")]
+ [InlineData("MainCompany.Name", "company.MainCompany.Name")]
+ [InlineData("Company.Name", "No property or field 'Name' exists in type 'Company'")]
+ [InlineData("DateTime", "company.DateTime")]
+ public void Parse_When_PrioritizePropertyOrFieldOverTheType_IsTrue(string expression, string result)
+ {
+ // Arrange
+ var config = new ParsingConfig
+ {
+ CustomTypeProvider = _dynamicTypeProviderMock.Object,
+ PrioritizePropertyOrFieldOverTheType = true
+ };
+ ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(Company), "company") };
+ var sut = new ExpressionParser(parameters, expression, null, config);
+
+ // Act
+ string parsedExpression;
+ try
+ {
+ parsedExpression = sut.Parse(null).ToString();
}
+ catch (ParseException e)
+ {
+ parsedExpression = e.Message;
+ }
+
+ // Assert
+ parsedExpression.Should().Be(result);
+ }
+
+ [Theory]
+ [InlineData("it.MainCompany.Name != null", "(company.MainCompany.Name != null)")]
+ [InlineData("@MainCompany.Companies.Count() > 0", "(company.MainCompany.Companies.Count() > 0)")]
+ [InlineData("Company.Equals(null, null)", "Equals(null, null)")]
+ [InlineData("MainCompany.Name", "Static property requires null instance, non-static property requires non-null instance.")] // Exception
+ [InlineData("DateTime", "'.' or '(' or string literal expected")] // Exception
+ [InlineData("Company.Name", "Static property requires null instance, non-static property requires non-null instance.")] // Exception
+ public void Parse_When_PrioritizePropertyOrFieldOverTheType_IsFalse(string expression, string result)
+ {
+ // Arrange
+ ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(Company), "company") };
- [Theory]
- [InlineData("it.MainCompany.Name != null", "(company.MainCompany.Name != null)")]
- [InlineData("@MainCompany.Companies.Count() > 0", "(company.MainCompany.Companies.Count() > 0)")]
- [InlineData("Company.Equals(null, null)", "Equals(null, null)")]
- [InlineData("MainCompany.Name", "company.MainCompany.Name")]
- [InlineData("Company.Name", "No property or field 'Name' exists in type 'Company'")]
- public void Parse_PrioritizePropertyOrFieldOverTheType(string expression, string result)
+ // Act
+ string parsedExpression;
+ try
{
- // Arrange
- ParameterExpression[] parameters = { ParameterExpressionHelper.CreateParameterExpression(typeof(Company), "company") };
var sut = new ExpressionParser(parameters, expression, null, _parsingConfig);
-
- // Act
- string parsedExpression;
- try
- {
- parsedExpression = sut.Parse(null).ToString();
- }
- catch (ParseException e)
- {
- parsedExpression = e.Message;
- }
-
- // Assert
- Check.That(parsedExpression).Equals(result);
+ parsedExpression = sut.Parse(null).ToString();
}
+ catch (Exception e)
+ {
+ parsedExpression = e.Message;
+ }
+
+ // Assert
+ parsedExpression.Should().StartWith(result);
}
-}
+}
\ No newline at end of file
diff --git a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.GroupBy.cs b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.GroupBy.cs
index 55b9a1af..46384adb 100644
--- a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.GroupBy.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.GroupBy.cs
@@ -13,7 +13,7 @@ public partial class QueryableTests
{
public class DateTimeTest
{
- public DateTimeTest Test { get; set; }
+ public DateTimeTest? Test { get; set; }
public DateTime? D { get; set; }
}
diff --git a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs
index ee365db3..82e854d7 100644
--- a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs
@@ -3,7 +3,6 @@
using System.IO;
using System.Linq.Dynamic.Core.Exceptions;
using System.Linq.Dynamic.Core.Tests.Helpers.Models;
-using FluentAssertions;
using Linq.PropertyTranslator.Core;
using QueryInterceptor.Core;
using Xunit;
diff --git a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Where.cs b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Where.cs
index 6ce39e54..5a340319 100644
--- a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Where.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Where.cs
@@ -7,283 +7,313 @@
using FluentAssertions;
using Xunit;
-namespace System.Linq.Dynamic.Core.Tests
+namespace System.Linq.Dynamic.Core.Tests;
+
+public partial class QueryableTests
{
- public partial class QueryableTests
+ [Fact]
+ public void Where_Dynamic()
{
- [Fact]
- public void Where_Dynamic()
- {
- // Arrange
- var testList = User.GenerateSampleModels(100, allowNullableProfiles: true);
- var qry = testList.AsQueryable();
-
- // Act
- var userById = qry.Where("Id=@0", testList[10].Id);
- var userByUserName = qry.Where("UserName=\"User5\"");
- var nullProfileCount = qry.Where("Profile=null");
- var userByFirstName = qry.Where("Profile!=null && Profile.FirstName=@0", testList[1].Profile.FirstName);
-
- // Assert
- Assert.Equal(testList[10], userById.Single());
- Assert.Equal(testList[5], userByUserName.Single());
- Assert.Equal(testList.Count(x => x.Profile == null), nullProfileCount.Count());
- Assert.Equal(testList[1], userByFirstName.Single());
- }
-
- [Fact]
- public void Where_Dynamic_CheckCastToObject()
- {
- // Arrange
- var testList = User.GenerateSampleModels(100, allowNullableProfiles: true);
- var qry = testList.AsQueryable();
-
- // Act
- string dynamicExpression = qry.Where("Profile == null").Expression.ToDebugView();
- string expresion = qry.Where(var1 => var1.Profile == null).Expression.ToDebugView();
-
- // Assert
- NFluent.Check.That(dynamicExpression).Equals(expresion);
- }
-
- [Theory]
- [InlineData("Fri, 10 May 2019 11:03:17 GMT", 11)]
- [InlineData("Fri, 10 May 2019 11:03:17 -07:00", 18)]
- public void Where_Dynamic_DateTimeIsParsedAsUTC(string time, int hours)
- {
- // Arrange
- var queryable = new List {
- new Example
- {
- TimeNull = new DateTime(2019, 5, 10, hours, 3, 17, DateTimeKind.Utc)
- }
- }.AsQueryable();
-
- // Act
- var parsingConfig = new ParsingConfig
+ // Arrange
+ var testList = User.GenerateSampleModels(100, allowNullableProfiles: true);
+ var qry = testList.AsQueryable();
+
+ // Act
+ var userById = qry.Where("Id=@0", testList[10].Id);
+ var userByUserName = qry.Where("UserName=\"User5\"");
+ var nullProfileCount = qry.Where("Profile=null");
+ var userByFirstName = qry.Where("Profile!=null && Profile.FirstName=@0", testList[1].Profile.FirstName);
+
+ // Assert
+ Assert.Equal(testList[10], userById.Single());
+ Assert.Equal(testList[5], userByUserName.Single());
+ Assert.Equal(testList.Count(x => x.Profile == null), nullProfileCount.Count());
+ Assert.Equal(testList[1], userByFirstName.Single());
+ }
+
+ [Fact]
+ public void Where_Dynamic_CheckCastToObject()
+ {
+ // Arrange
+ var testList = User.GenerateSampleModels(100, allowNullableProfiles: true);
+ var qry = testList.AsQueryable();
+
+ // Act
+ string dynamicExpression = qry.Where("Profile == null").Expression.ToDebugView();
+ string expresion = qry.Where(var1 => var1.Profile == null).Expression.ToDebugView();
+
+ // Assert
+ NFluent.Check.That(dynamicExpression).Equals(expresion);
+ }
+
+ [Theory]
+ [InlineData("Fri, 10 May 2019 11:03:17 GMT", 11)]
+ [InlineData("Fri, 10 May 2019 11:03:17 -07:00", 18)]
+ public void Where_Dynamic_DateTimeIsParsedAsUTC(string time, int hours)
+ {
+ // Arrange
+ var queryable = new List {
+ new Example
{
- DateTimeIsParsedAsUTC = true
- };
- var result = queryable.Where(parsingConfig, $"it.TimeNull >= \"{time}\"");
-
- // Assert
- Assert.Equal(1, result.Count());
- }
-
- ///
- /// https://github.com/StefH/System.Linq.Dynamic.Core/issues/19
- ///
- [Fact]
- public void Where_Dynamic_DateTime_NotEquals_Null()
+ TimeNull = new DateTime(2019, 5, 10, hours, 3, 17, DateTimeKind.Utc)
+ }
+ }.AsQueryable();
+
+ // Act
+ var parsingConfig = new ParsingConfig
{
- //Arrange
- IQueryable queryable = new[] { new Post() }.AsQueryable();
+ DateTimeIsParsedAsUTC = true
+ };
+ var result = queryable.Where(parsingConfig, $"it.TimeNull >= \"{time}\"");
- //Act
- var expected = queryable.Where(p => p.PostDate != null).ToArray();
- var result1 = queryable.Where("PostDate != null").ToArray();
- var result2 = queryable.Where("null != PostDate").ToArray();
+ // Assert
+ Assert.Equal(1, result.Count());
+ }
- //Assert
- Assert.Equal(expected, result1);
- Assert.Equal(expected, result2);
- }
+ ///
+ /// https://github.com/StefH/System.Linq.Dynamic.Core/issues/19
+ ///
+ [Fact]
+ public void Where_Dynamic_DateTime_NotEquals_Null()
+ {
+ //Arrange
+ IQueryable queryable = new[] { new Post() }.AsQueryable();
- [Fact]
- public void Where_Dynamic_DateTime_Equals_Null()
- {
- //Arrange
- IQueryable queryable = new[] { new Post() }.AsQueryable();
+ //Act
+ var expected = queryable.Where(p => p.PostDate != null).ToArray();
+ var result1 = queryable.Where("PostDate != null").ToArray();
+ var result2 = queryable.Where("null != PostDate").ToArray();
- //Act
- var expected = queryable.Where(p => p.PostDate == null).ToArray();
- var result1 = queryable.Where("PostDate == null").ToArray();
- var result2 = queryable.Where("null == PostDate").ToArray();
+ //Assert
+ Assert.Equal(expected, result1);
+ Assert.Equal(expected, result2);
+ }
- //Assert
- Assert.Equal(expected, result1);
- Assert.Equal(expected, result2);
- }
+ [Fact]
+ public void Where_Dynamic_DateTime_Equals_Null()
+ {
+ //Arrange
+ IQueryable queryable = new[] { new Post() }.AsQueryable();
- [Fact]
- public void Where_Dynamic_IQueryable_LambdaExpression()
- {
- // Arrange
- var queryable = (IQueryable)new[] { new User { Income = 5 } }.AsQueryable();
+ //Act
+ var expected = queryable.Where(p => p.PostDate == null).ToArray();
+ var result1 = queryable.Where("PostDate == null").ToArray();
+ var result2 = queryable.Where("null == PostDate").ToArray();
- Expression> userExpression = u => u.Income > 1;
- LambdaExpression lambdaExpression = userExpression;
+ //Assert
+ Assert.Equal(expected, result1);
+ Assert.Equal(expected, result2);
+ }
- // Act
- var result = queryable.Where(lambdaExpression).ToDynamicArray();
+ [Fact]
+ public void Where_Dynamic_IQueryable_LambdaExpression()
+ {
+ // Arrange
+ var queryable = (IQueryable)new[] { new User { Income = 5 } }.AsQueryable();
- // Assert
- result.Should().HaveCount(1);
- }
+ Expression> userExpression = u => u.Income > 1;
+ LambdaExpression lambdaExpression = userExpression;
- [Fact]
- public void Where_Dynamic_IQueryableT_LambdaExpression()
- {
- // Arrange
- var queryable = new[] { new User { Income = 5 } }.AsQueryable();
+ // Act
+ var result = queryable.Where(lambdaExpression).ToDynamicArray();
- Expression> userExpression = u => u.Income > 1;
- LambdaExpression lambdaExpression = userExpression;
+ // Assert
+ result.Should().HaveCount(1);
+ }
- // Act
- var result = queryable.Where(lambdaExpression);
+ [Fact]
+ public void Where_Dynamic_IQueryableT_LambdaExpression()
+ {
+ // Arrange
+ var queryable = new[] { new User { Income = 5 } }.AsQueryable();
- // Assert
- result.Should().HaveCount(1);
- }
+ Expression> userExpression = u => u.Income > 1;
+ LambdaExpression lambdaExpression = userExpression;
- [Fact]
- public void Where_Dynamic_Exceptions()
- {
- //Arrange
- var testList = User.GenerateSampleModels(100, allowNullableProfiles: true);
- var qry = testList.AsQueryable();
-
- //Act
- Assert.Throws(() => qry.Where("Id"));
- Assert.Throws(() => qry.Where("Bad=3"));
- Assert.Throws(() => qry.Where("Id=123"));
-
- Assert.Throws(() => DynamicQueryableExtensions.Where(null, "Id=1"));
- Assert.Throws(() => qry.Where((string)null));
- Assert.Throws(() => qry.Where(""));
- Assert.Throws(() => qry.Where(" "));
- }
-
- [Fact]
- public void Where_Dynamic_StringQuoted()
- {
- // Arrange
- var testList = User.GenerateSampleModels(2, allowNullableProfiles: true);
- testList[0].UserName = @"This \""is\"" a test.";
- var qry = testList.AsQueryable();
-
- // Act
- // var result1a = qry.Where(@"UserName == ""This \\""is\\"" a test.""").ToArray();
- var result1b = qry.Where("UserName == \"This \\\\\\\"is\\\\\\\" a test.\"").ToArray();
- var result2a = qry.Where("UserName == @0", @"This \""is\"" a test.").ToArray();
- var result2b = qry.Where("UserName == @0", "This \\\"is\\\" a test.").ToArray();
-
- var expected = qry.Where(x => x.UserName == @"This \""is\"" a test.").ToArray();
-
- // Assert
- Assert.Single(expected);
- // Assert.Equal(expected, result1a);
- Assert.Equal(expected, result1b);
- Assert.Equal(expected, result2a);
- Assert.Equal(expected, result2b);
- }
-
- [Fact]
- public void Where_Dynamic_EmptyString()
- {
- // Arrange
- var testList = User.GenerateSampleModels(2, allowNullableProfiles: true);
- var qry = testList.AsQueryable();
-
- // Act
- var expected1 = qry.Where(u => u.UserName != string.Empty).ToArray();
- var expected2 = qry.Where(u => u.UserName != "").ToArray();
- var resultDynamic1 = qry.Where("UserName != @0", string.Empty).ToArray();
- var resultDynamic2 = qry.Where("UserName != @0", "").ToArray();
-
- // Assert
- resultDynamic1.Should().Contain(expected1);
- resultDynamic2.Should().Contain(expected2);
- }
-
- [Fact]
- public void Where_Dynamic_SelectNewObjects()
- {
- //Arrange
- var testList = User.GenerateSampleModels(100, allowNullableProfiles: true);
- var qry = testList.AsQueryable();
+ // Act
+ var result = queryable.Where(lambdaExpression);
- //Act
- var expectedResult = testList.Where(x => x.Income > 4000).Select(x => new { Id = x.Id, Income = x.Income + 1111 });
- var dynamicList = qry.Where("Income > @0", 4000).ToDynamicList();
+ // Assert
+ result.Should().HaveCount(1);
+ }
- var newUsers = dynamicList.Select(x => new { Id = x.Id, Income = x.Income + 1111 });
- Assert.Equal(newUsers.Cast