diff --git a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs index 2c4e07ce..07ef88c9 100644 --- a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs +++ b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs @@ -504,13 +504,27 @@ Expression ParseComparisonOperator() if (!typesAreSameAndImplementCorrectInterface) { - if (left.Type.GetTypeInfo().IsClass && right is ConstantExpression && HasImplicitConversion(left.Type, right.Type)) + if (left.Type.GetTypeInfo().IsClass && right is ConstantExpression) { - left = Expression.Convert(left, right.Type); + if (HasImplicitConversion(left.Type, right.Type)) + { + left = Expression.Convert(left, right.Type); + } + else if (HasImplicitConversion(right.Type, left.Type)) + { + right = Expression.Convert(right, left.Type); + } } - else if (right.Type.GetTypeInfo().IsClass && left is ConstantExpression && HasImplicitConversion(right.Type, left.Type)) + else if (right.Type.GetTypeInfo().IsClass && left is ConstantExpression) { - right = Expression.Convert(right, left.Type); + if (HasImplicitConversion(right.Type, left.Type)) + { + right = Expression.Convert(right, left.Type); + } + else if (HasImplicitConversion(left.Type, right.Type)) + { + left = Expression.Convert(left, right.Type); + } } else { diff --git a/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs b/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs index dda8af63..7cd30ac9 100644 --- a/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs +++ b/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs @@ -84,14 +84,87 @@ public override string ToString() } } + public class CustomClassWithReversedImplicitConversion + { + public CustomClassWithReversedImplicitConversion(string origin) + { + Origin = origin; + } + + public string Origin { get; } + + public static implicit operator string(CustomClassWithReversedImplicitConversion origin) + { + return origin.ToString(); + } + + public override string ToString() + { + return Origin; + } + } + + public class CustomClassWithValueTypeImplicitConversion + { + public CustomClassWithValueTypeImplicitConversion(int origin) + { + Origin = origin; + } + + public int Origin { get; } + + public static implicit operator CustomClassWithValueTypeImplicitConversion(int origin) + { + return new CustomClassWithValueTypeImplicitConversion(origin); + } + + public override string ToString() + { + return Origin.ToString(); + } + } + + public class CustomClassWithReversedValueTypeImplicitConversion + { + public CustomClassWithReversedValueTypeImplicitConversion(int origin) + { + Origin = origin; + } + + public int Origin { get; } + + public static implicit operator int(CustomClassWithReversedValueTypeImplicitConversion origin) + { + return origin.Origin; + } + + public override string ToString() + { + return Origin.ToString(); + } + } + public class TestImplicitConversionContainer { - public TestImplicitConversionContainer(CustomClassWithOneWayImplicitConversion oneWay) + public TestImplicitConversionContainer( + CustomClassWithOneWayImplicitConversion oneWay, + CustomClassWithReversedImplicitConversion reversed, + CustomClassWithValueTypeImplicitConversion valueType, + CustomClassWithReversedValueTypeImplicitConversion reversedValueType) { OneWay = oneWay; + Reversed = Reversed; + ValueType = valueType; + ReversedValueType = reversedValueType; } public CustomClassWithOneWayImplicitConversion OneWay { get; } + + public CustomClassWithReversedImplicitConversion Reversed { get; } + + public CustomClassWithValueTypeImplicitConversion ValueType { get; } + + public CustomClassWithReversedValueTypeImplicitConversion ReversedValueType { get; } } public class TextHolder @@ -791,14 +864,66 @@ public void DynamicExpressionParser_ParseLambda_With_Concat_CustomType_String() public void DynamicExpressionParser_ParseLambda_With_One_Way_Implicit_Conversions() { // Arrange - var testValue = "test"; - var container = new TestImplicitConversionContainer(testValue); - var expressionText = $"OneWay == \"{testValue}\""; + var testString = "test"; + var testInt = 6; + var container = new TestImplicitConversionContainer(testString, new CustomClassWithReversedImplicitConversion(testString), testInt, new CustomClassWithReversedValueTypeImplicitConversion(testInt)); - // Act - var lambda = DynamicExpressionParser.ParseLambda(ParsingConfig.Default, false, expressionText); + var expressionTextString = $"OneWay == \"{testString}\""; + var expressionTextReversed = $"Reversed == \"{testString}\""; + var expressionTextValueType = $"ValueType == {testInt}"; + var expressionTextReversedValueType = $"ReversedValueType == {testInt}"; - // Assert + var invertedExpressionTextString = $"\"{testString}\" == OneWay"; + var invertedExpressionTextReversed = $"\"{testString}\" == Reversed"; + var invertedExpressionTextValueType = $"{testInt} == ValueType"; + var invertedExpressionTextReversedValueType = $"{testInt} == ReversedValueType"; + + // Act 1 + var lambda = DynamicExpressionParser.ParseLambda(ParsingConfig.Default, false, expressionTextString); + + // Assert 1 + Assert.NotNull(lambda); + + // Act 2 + lambda = DynamicExpressionParser.ParseLambda(ParsingConfig.Default, false, expressionTextReversed); + + // Assert 2 + Assert.NotNull(lambda); + + // Act 3 + lambda = DynamicExpressionParser.ParseLambda(ParsingConfig.Default, false, expressionTextValueType); + + // Assert 3 + Assert.NotNull(lambda); + + // Act 4 + lambda = DynamicExpressionParser.ParseLambda(ParsingConfig.Default, false, expressionTextReversedValueType); + + // Assert 4 + Assert.NotNull(lambda); + + // Act 5 + lambda = DynamicExpressionParser.ParseLambda(ParsingConfig.Default, false, invertedExpressionTextString); + + // Assert 5 + Assert.NotNull(lambda); + + // Act 6 + lambda = DynamicExpressionParser.ParseLambda(ParsingConfig.Default, false, invertedExpressionTextReversed); + + // Assert 6 + Assert.NotNull(lambda); + + // Act 7 + lambda = DynamicExpressionParser.ParseLambda(ParsingConfig.Default, false, invertedExpressionTextValueType); + + // Assert 7 + Assert.NotNull(lambda); + + // Act 8 + lambda = DynamicExpressionParser.ParseLambda(ParsingConfig.Default, false, invertedExpressionTextReversedValueType); + + // Assert 8 Assert.NotNull(lambda); }