Skip to content

Commit 12704c2

Browse files
arjenvrhStefH
authored andcommitted
Feature: Added support for implicit type conversions (#166)
* Update ExpressionParser.cs * Update ExpressionParser.cs * Update ExpressionParser.cs * Unit test for implicit casting * Unit test for implicit casting
1 parent e3d5f52 commit 12704c2

File tree

4 files changed

+66
-2
lines changed

4 files changed

+66
-2
lines changed

src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs

+20-1
Original file line numberDiff line numberDiff line change
@@ -499,9 +499,21 @@ Expression ParseComparisonOperator()
499499
}
500500
}
501501

502+
502503
if (!typesAreSameAndImplementCorrectInterface)
503504
{
504-
CheckAndPromoteOperands(isEquality ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures), op.Text, ref left, ref right, op.Pos);
505+
if (left.Type.GetTypeInfo().IsClass && right is ConstantExpression && HasImplicitConversion(left.Type, right.Type))
506+
{
507+
left = Expression.Convert(left, right.Type);
508+
}
509+
else if (right.Type.GetTypeInfo().IsClass && left is ConstantExpression && HasImplicitConversion(right.Type, left.Type))
510+
{
511+
right = Expression.Convert(right, left.Type);
512+
}
513+
else
514+
{
515+
CheckAndPromoteOperands(isEquality ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures), op.Text, ref left, ref right, op.Pos);
516+
}
505517
}
506518
}
507519

@@ -533,6 +545,13 @@ Expression ParseComparisonOperator()
533545
return left;
534546
}
535547

548+
private bool HasImplicitConversion(Type baseType, Type targetType)
549+
{
550+
return baseType.GetMethods(BindingFlags.Public | BindingFlags.Static)
551+
.Where(mi => mi.Name == "op_Implicit" && mi.ReturnType == targetType)
552+
.Any(mi => mi.GetParameters().FirstOrDefault()?.ParameterType == baseType);
553+
}
554+
536555
private ConstantExpression ParseEnumToConstantExpression(int pos, Type leftType, ConstantExpression constantExpr)
537556
{
538557
return Expression.Constant(ParseConstantExpressionToEnum(pos, leftType, constantExpr), leftType);

test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs

+28
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,34 @@ public void ExpressionTests_SkipAndTake()
13851385
}
13861386
}
13871387

1388+
[Fact]
1389+
public void ExpressionTests_ImplicitCast()
1390+
{
1391+
//Arrange
1392+
Guid code1 = new Guid("651E08E3-85B1-42D1-80AF-68E28E2B7DA6");
1393+
Guid code2 = new Guid("6451FEB2-3226-41D0-961C-B72B7B5A0157");
1394+
1395+
var samples = User.GenerateSampleModels(3);
1396+
samples[0].State = new UserState() { StatusCode = code1, Description = "alive" };
1397+
samples[1].State = new UserState() { StatusCode = code2, Description = "deceased" };
1398+
1399+
//Act
1400+
string queryString = "State == @0";
1401+
IList<User> result = samples.AsQueryable().Where(queryString, code1).ToList();
1402+
1403+
string queryString2 = "@0 == State";
1404+
IList<User> result2 = samples.AsQueryable().Where(queryString2, code1).ToList();
1405+
1406+
//Assert
1407+
Assert.Equal(1, result.Count);
1408+
Assert.Equal(code1, result[0].State.StatusCode);
1409+
Assert.Equal("alive", result[0].State.Description);
1410+
1411+
Assert.Equal(1, result2.Count);
1412+
Assert.Equal(code1, result2[0].State.StatusCode);
1413+
Assert.Equal("alive", result2[0].State.Description);
1414+
}
1415+
13881416
[Fact]
13891417
public void ExpressionTests_StringCompare()
13901418
{

test/System.Linq.Dynamic.Core.Tests/Helpers/Models/User.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public class User
1414

1515
public UserProfile Profile { get; set; }
1616

17+
public UserState State { get; set; }
18+
1719
public List<Role> Roles { get; set; }
1820

1921
public bool TestMethod1()
@@ -62,4 +64,4 @@ public static IList<User> GenerateSampleModels(int total, bool allowNullableProf
6264
return list.ToArray();
6365
}
6466
}
65-
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace System.Linq.Dynamic.Core.Tests.Helpers.Models
6+
{
7+
public class UserState
8+
{
9+
public Guid StatusCode { get; set; }
10+
public string Description { get; set; }
11+
12+
public static implicit operator Guid(UserState state)
13+
=> state?.StatusCode ?? Guid.Empty;
14+
}
15+
}

0 commit comments

Comments
 (0)