Skip to content

Commit 9f59211

Browse files
authored
Fixed adding Enum and integer (#953)
1 parent 09d558a commit 9f59211

File tree

4 files changed

+94
-19
lines changed

4 files changed

+94
-19
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public ExpressionPromoter(ParsingConfig config)
122122

123123
if (TypeHelper.IsCompatibleWith(returnType, type))
124124
{
125-
if (type == typeof(decimal) && TypeHelper.IsEnumType(sourceExpression.Type))
125+
if (TypeHelper.TypesAreEqual(type, typeof(decimal)) && TypeHelper.IsEnumType(sourceExpression.Type))
126126
{
127127
return Expression.Convert(Expression.Convert(sourceExpression, Enum.GetUnderlyingType(sourceExpression.Type)), type);
128128
}

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

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,20 @@ public static bool IsCompatibleWith(Type source, Type target)
8383
return target.IsAssignableFrom(source);
8484
}
8585

86-
Type st = GetNonNullableType(source);
87-
Type tt = GetNonNullableType(target);
86+
var sourceType = GetNonNullableType(source);
87+
var targetType = GetNonNullableType(target);
8888

89-
if (st != source && tt == target)
89+
if (sourceType != source && targetType == target)
9090
{
9191
return false;
9292
}
9393

94-
TypeCode sc = st.GetTypeInfo().IsEnum ? TypeCode.Int64 : Type.GetTypeCode(st);
95-
TypeCode tc = tt.GetTypeInfo().IsEnum ? TypeCode.Int64 : Type.GetTypeCode(tt);
96-
switch (sc)
94+
var sourceTypeCode = sourceType.GetTypeInfo().IsEnum ? TypeCode.Int32 : Type.GetTypeCode(sourceType);
95+
var targetTypeCode = targetType.GetTypeInfo().IsEnum ? TypeCode.Int32 : Type.GetTypeCode(targetType);
96+
switch (sourceTypeCode)
9797
{
9898
case TypeCode.SByte:
99-
switch (tc)
99+
switch (targetTypeCode)
100100
{
101101
case TypeCode.SByte:
102102
case TypeCode.Int16:
@@ -110,7 +110,7 @@ public static bool IsCompatibleWith(Type source, Type target)
110110
break;
111111

112112
case TypeCode.Byte:
113-
switch (tc)
113+
switch (targetTypeCode)
114114
{
115115
case TypeCode.Byte:
116116
case TypeCode.Int16:
@@ -127,7 +127,7 @@ public static bool IsCompatibleWith(Type source, Type target)
127127
break;
128128

129129
case TypeCode.Int16:
130-
switch (tc)
130+
switch (targetTypeCode)
131131
{
132132
case TypeCode.Int16:
133133
case TypeCode.Int32:
@@ -140,7 +140,7 @@ public static bool IsCompatibleWith(Type source, Type target)
140140
break;
141141

142142
case TypeCode.UInt16:
143-
switch (tc)
143+
switch (targetTypeCode)
144144
{
145145
case TypeCode.UInt16:
146146
case TypeCode.Int32:
@@ -155,7 +155,7 @@ public static bool IsCompatibleWith(Type source, Type target)
155155
break;
156156

157157
case TypeCode.Int32:
158-
switch (tc)
158+
switch (targetTypeCode)
159159
{
160160
case TypeCode.Int32:
161161
case TypeCode.Int64:
@@ -167,7 +167,7 @@ public static bool IsCompatibleWith(Type source, Type target)
167167
break;
168168

169169
case TypeCode.UInt32:
170-
switch (tc)
170+
switch (targetTypeCode)
171171
{
172172
case TypeCode.UInt32:
173173
case TypeCode.Int64:
@@ -180,7 +180,7 @@ public static bool IsCompatibleWith(Type source, Type target)
180180
break;
181181

182182
case TypeCode.Int64:
183-
switch (tc)
183+
switch (targetTypeCode)
184184
{
185185
case TypeCode.Int64:
186186
case TypeCode.Single:
@@ -191,7 +191,7 @@ public static bool IsCompatibleWith(Type source, Type target)
191191
break;
192192

193193
case TypeCode.UInt64:
194-
switch (tc)
194+
switch (targetTypeCode)
195195
{
196196
case TypeCode.UInt64:
197197
case TypeCode.Single:
@@ -202,7 +202,7 @@ public static bool IsCompatibleWith(Type source, Type target)
202202
break;
203203

204204
case TypeCode.Single:
205-
switch (tc)
205+
switch (targetTypeCode)
206206
{
207207
case TypeCode.Single:
208208
case TypeCode.Double:
@@ -211,7 +211,7 @@ public static bool IsCompatibleWith(Type source, Type target)
211211
break;
212212

213213
default:
214-
if (st == tt)
214+
if (sourceType == targetType)
215215
{
216216
return true;
217217
}
@@ -471,6 +471,11 @@ public static Type GetUnderlyingType(Type type)
471471
return type;
472472
}
473473

474+
public static bool TypesAreEqual(Type type, Type typeToCheck)
475+
{
476+
return GetNullableType(type) == GetNullableType(typeToCheck);
477+
}
478+
474479
public static IList<Type> GetSelfAndBaseTypes(Type type, bool excludeObject = false)
475480
{
476481
if (type.GetTypeInfo().IsInterface)

test/System.Linq.Dynamic.Core.Tests/Parser/TypeHelperTests.cs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public void TypeHelper_IsCompatibleWith_SameTypes_True()
4545
}
4646

4747
[Fact]
48-
public void TypeHelper_IsCompatibleWith_True()
48+
public void TypeHelper_IsCompatibleWith_Int_And_Long_Returns_True()
4949
{
5050
// Assign + Act
5151
var result = TypeHelper.IsCompatibleWith(typeof(int), typeof(long));
@@ -54,8 +54,52 @@ public void TypeHelper_IsCompatibleWith_True()
5454
Check.That(result).IsTrue();
5555
}
5656

57+
[Theory]
58+
59+
// True (enum underlying Int32 compatible targets)
60+
[InlineData(typeof(DayOfWeek), true)]
61+
[InlineData(typeof(DayOfWeek?), true)]
62+
[InlineData(typeof(int), true)]
63+
[InlineData(typeof(int?), true)]
64+
[InlineData(typeof(long), true)]
65+
[InlineData(typeof(long?), true)]
66+
[InlineData(typeof(float), true)]
67+
[InlineData(typeof(float?), true)]
68+
[InlineData(typeof(double), true)]
69+
[InlineData(typeof(double?), true)]
70+
[InlineData(typeof(decimal), true)]
71+
[InlineData(typeof(decimal?), true)]
72+
[InlineData(typeof(object), true)]
73+
74+
// False (not compatible with enum's Int32 widening rules or reference types)
75+
[InlineData(typeof(char), false)]
76+
[InlineData(typeof(char?), false)]
77+
[InlineData(typeof(short), false)]
78+
[InlineData(typeof(short?), false)]
79+
[InlineData(typeof(byte), false)]
80+
[InlineData(typeof(byte?), false)]
81+
[InlineData(typeof(sbyte), false)]
82+
[InlineData(typeof(sbyte?), false)]
83+
[InlineData(typeof(ushort), false)]
84+
[InlineData(typeof(ushort?), false)]
85+
[InlineData(typeof(uint), false)]
86+
[InlineData(typeof(uint?), false)]
87+
[InlineData(typeof(ulong), false)]
88+
[InlineData(typeof(ulong?), false)]
89+
[InlineData(typeof(bool), false)]
90+
[InlineData(typeof(bool?), false)]
91+
[InlineData(typeof(string), false)]
92+
public void TypeHelper_IsCompatibleWith_Enum(Type targetType, bool expected)
93+
{
94+
// Assign + Act
95+
var result = TypeHelper.IsCompatibleWith(typeof(DayOfWeek), targetType);
96+
97+
// Assert
98+
result.Should().Be(expected);
99+
}
100+
57101
[Fact]
58-
public void TypeHelper_IsCompatibleWith_False()
102+
public void TypeHelper_IsCompatibleWith_Long_And_Int_Returns_False()
59103
{
60104
// Assign + Act
61105
var result = TypeHelper.IsCompatibleWith(typeof(long), typeof(int));

test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,32 @@ public void Select_Dynamic_Add_Strings()
202202
Assert.Equal(range.Select(x => x + "c").ToArray(), rangeResult.Cast<string>().ToArray());
203203
}
204204

205+
[Fact]
206+
public void Select_Dynamic_Add_DayOfWeekEnum_And_Integer()
207+
{
208+
// Arrange
209+
var range = new DayOfWeek[] { DayOfWeek.Monday };
210+
211+
// Act
212+
var rangeResult = range.AsQueryable().Select("it + 1");
213+
214+
// Assert
215+
Assert.Equal(range.Select(x => x + 1).ToArray(), rangeResult.Cast<DayOfWeek>().ToArray());
216+
}
217+
218+
[Fact]
219+
public void Select_Dynamic_Add_Integer_And_DayOfWeekEnum()
220+
{
221+
// Arrange
222+
var range = new int[] { 1 };
223+
224+
// Act
225+
var rangeResult = range.AsQueryable().Select("it + DayOfWeek.Monday");
226+
227+
// Assert
228+
Assert.Equal(range.Select(x => x + DayOfWeek.Monday).Cast<int>().ToArray(), rangeResult.Cast<int>().ToArray());
229+
}
230+
205231
[Fact]
206232
public void Select_Dynamic_WithIncludes()
207233
{

0 commit comments

Comments
 (0)