Skip to content

Commit 48a0075

Browse files
authored
Fix generic comparer type (#619)
* wip * x * . * 20-preview-01
1 parent 40f9e92 commit 48a0075

File tree

4 files changed

+88
-13
lines changed

4 files changed

+88
-13
lines changed

src/System.Linq.Dynamic.Core/DynamicClassFactory.cs

+6-4
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public static Type CreateGenericComparerType(Type comparerGenericType, Type comp
108108
var compareMethodGeneric = comparerGenericType.GetMethod("Compare");
109109
var compareMethod = typeof(IComparer).GetMethod("Compare");
110110
var compareCtor = comparerType.GetConstructor(Type.EmptyTypes);
111+
var genericType = comparerGenericType.GetGenericArguments()[0];
111112

112113
var typeBuilder = ModuleBuilder.DefineType(key, TypeAttributes.AnsiClass | TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoLayout, typeof(object));
113114
typeBuilder.AddInterfaceImplementation(comparerGenericType);
@@ -134,9 +135,9 @@ public static Type CreateGenericComparerType(Type comparerGenericType, Type comp
134135
methodBuilderIL.Emit(OpCodes.Ldarg_0);
135136
methodBuilderIL.Emit(OpCodes.Ldfld, fieldBuilder);
136137
methodBuilderIL.Emit(OpCodes.Ldarg_1);
137-
methodBuilderIL.Emit(OpCodes.Box, typeof(int));
138+
methodBuilderIL.Emit(OpCodes.Box, genericType);
138139
methodBuilderIL.Emit(OpCodes.Ldarg_2);
139-
methodBuilderIL.Emit(OpCodes.Box, typeof(int));
140+
methodBuilderIL.Emit(OpCodes.Box, genericType);
140141
methodBuilderIL.Emit(OpCodes.Callvirt, compareMethod);
141142
methodBuilderIL.Emit(OpCodes.Ret);
142143

@@ -443,9 +444,10 @@ public static Type CreateType([NotNull] IList<DynamicProperty> properties, bool
443444

444445
/// <summary>
445446
/// Generates the key.
446-
/// Anonymous classes are generics based. The generic classes are distinguished by number of parameters and name of parameters. The specific types of the parameters are the generic arguments.
447+
/// Anonymous classes are generics based. The generic classes are distinguished by number of parameters and name of parameters.
448+
/// The specific types of the parameters are the generic arguments.
447449
/// </summary>
448-
/// <param name="dynamicProperties">The dynamic propertys.</param>
450+
/// <param name="dynamicProperties">The dynamic properties.</param>
449451
/// <param name="createParameterCtor">if set to <c>true</c> [create parameter ctor].</param>
450452
/// <returns></returns>
451453
private static string GenerateKey(IEnumerable<DynamicProperty> dynamicProperties, bool createParameterCtor)

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

+56-6
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,79 @@ namespace System.Linq.Dynamic.Core.Tests
88
public class DynamicClassFactoryTests
99
{
1010
[Fact]
11-
public void CreateGenericComparerType()
11+
public void CreateGenericComparerTypeForInt()
1212
{
1313
// Assign
14-
var comparer = new IntComparer();
14+
var comparer = new CustomCaseInsensitiveComparer();
1515
var comparerGenericType = typeof(IComparer<>).MakeGenericType(typeof(int));
16+
var a = 1;
17+
var b = 2;
1618

1719
// Act
1820
var type = DynamicClassFactory.CreateGenericComparerType(comparerGenericType, comparer.GetType());
1921

2022
// Assert
2123
var instance = (IComparer<int>)Activator.CreateInstance(type);
22-
int greaterThan = instance.Compare(1, 2);
24+
int greaterThan = instance.Compare(a, b);
2325
greaterThan.Should().Be(1);
2426

25-
int equal = instance.Compare(1, 1);
27+
int equal = instance.Compare(a, a);
2628
equal.Should().Be(0);
2729

28-
int lessThan = instance.Compare(2, 1);
30+
int lessThan = instance.Compare(b, a);
31+
lessThan.Should().Be(-1);
32+
}
33+
34+
[Fact]
35+
public void CreateGenericComparerTypeForString()
36+
{
37+
// Assign
38+
var comparer = new CustomCaseInsensitiveComparer();
39+
var comparerGenericType = typeof(IComparer<>).MakeGenericType(typeof(string));
40+
var a = "a";
41+
var b = "b";
42+
43+
// Act
44+
var type = DynamicClassFactory.CreateGenericComparerType(comparerGenericType, comparer.GetType());
45+
46+
// Assert
47+
var instance = (IComparer<string>)Activator.CreateInstance(type);
48+
int greaterThan = instance.Compare(a, b);
49+
greaterThan.Should().Be(1);
50+
51+
int equal = instance.Compare(a, a);
52+
equal.Should().Be(0);
53+
54+
int lessThan = instance.Compare(b, a);
55+
lessThan.Should().Be(-1);
56+
}
57+
58+
[Fact]
59+
public void CreateGenericComparerTypeForDateTime()
60+
{
61+
// Assign
62+
var comparer = new CustomCaseInsensitiveComparer();
63+
var comparerGenericType = typeof(IComparer<>).MakeGenericType(typeof(DateTime));
64+
var a = new DateTime(2022, 1, 1);
65+
var b = new DateTime(2023, 1, 1);
66+
67+
// Act
68+
var type = DynamicClassFactory.CreateGenericComparerType(comparerGenericType, comparer.GetType());
69+
70+
// Assert
71+
var instance = (IComparer<DateTime>)Activator.CreateInstance(type);
72+
int greaterThan = instance.Compare(a, b);
73+
greaterThan.Should().Be(1);
74+
75+
int equal = instance.Compare(a, a);
76+
equal.Should().Be(0);
77+
78+
int lessThan = instance.Compare(b, a);
2979
lessThan.Should().Be(-1);
3080
}
3181
}
3282

33-
public class IntComparer : IComparer
83+
public class CustomCaseInsensitiveComparer : IComparer
3484
{
3585
public int Compare(object x, object y)
3686
{

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

+25-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ public int Compare(int x, int y)
1616
}
1717
}
1818

19+
public class StringComparerT : IComparer<string>
20+
{
21+
public int Compare(string x, string y)
22+
{
23+
return new CaseInsensitiveComparer().Compare(y, x);
24+
}
25+
}
26+
1927
public class ObjectComparer : IComparer
2028
{
2129
public int Compare(object x, object y)
@@ -40,7 +48,7 @@ public void OrderBy_Dynamic_IComparer_StringComparer()
4048
}
4149

4250
[Fact]
43-
public void OrderBy_Dynamic_IComparer_ObjectComparer()
51+
public void OrderBy_Dynamic_IComparer_ObjectComparer_Int()
4452
{
4553
// Arrange
4654
var testList = User.GenerateSampleModels(3);
@@ -54,6 +62,21 @@ public void OrderBy_Dynamic_IComparer_ObjectComparer()
5462
Assert.Equal(orderBy, orderByDynamic);
5563
}
5664

65+
[Fact]
66+
public void OrderBy_Dynamic_IComparer_ObjectComparer_String()
67+
{
68+
// Arrange
69+
var testList = User.GenerateSampleModels(3);
70+
var qry = testList.AsQueryable();
71+
72+
// Act
73+
var orderBy = testList.OrderBy(x => x.UserName, new StringComparerT()).ToArray();
74+
var orderByDynamic = qry.OrderBy("UserName", new ObjectComparer()).ToArray();
75+
76+
// Assert
77+
Assert.Equal(orderBy, orderByDynamic);
78+
}
79+
5780
[Fact]
5881
public void OrderBy_Dynamic_IComparer_IntComparerT()
5982
{
@@ -149,4 +172,4 @@ public void OrderBy_Dynamic_Exceptions()
149172
Assert.Throws<ArgumentException>(() => qry.OrderBy(" "));
150173
}
151174
}
152-
}
175+
}

version.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<Project>
22
<PropertyGroup>
3-
<PatchVersion>19</PatchVersion>
3+
<PatchVersion>20-preview-01</PatchVersion>
44
</PropertyGroup>
55
</Project>

0 commit comments

Comments
 (0)