Skip to content

Commit 79cb06d

Browse files
Merge pull request #381 from Lempireqc/master
save
2 parents 31945cf + 9034f83 commit 79cb06d

File tree

4 files changed

+219
-11
lines changed

4 files changed

+219
-11
lines changed

Z.Dynamic.Core.Lab/Program.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class Program
66
{
77
static void Main(string[] args)
88
{
9-
Request_OrderBy_StringComparer.Execute();
9+
Request_GroupBy_IEqualityComparer.Execute();
1010
}
1111
}
1212
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Linq.Dynamic.Core;
5+
using System.Text;
6+
7+
namespace Z.Dynamic.Core.Lab
8+
{
9+
class Request_GroupBy_IEqualityComparer
10+
{
11+
public class Customer
12+
{
13+
public string City { get; set; }
14+
public List<Order> Orders { get; set; }
15+
public string CompanyName { get; set; }
16+
public string Phone { get; set; }
17+
}
18+
public class Order
19+
{
20+
}
21+
22+
public static void Execute()
23+
{
24+
List<Customer> customers = new List<Customer>() { new Customer() { City = "ZZZ" }, new Customer() { City = "ZzZ" } };
25+
var check = customers.GroupBy(x => x.City, StringComparer.InvariantCultureIgnoreCase).ToList();
26+
27+
var query = customers.AsQueryable().GroupBy("City", StringComparer.InvariantCultureIgnoreCase).ToDynamicList();
28+
var queray = customers.AsQueryable().GroupBy("City", "new(CompanyName as Name, Phone)", StringComparer.InvariantCultureIgnoreCase).ToDynamicList();
29+
var queraay = customers.AsQueryable().GroupBy("City", "new(CompanyName as Name, Phone)" ).ToDynamicList();
30+
}
31+
}
32+
}

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

+107-10
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,17 @@ public static dynamic FirstOrDefault([NotNull] this IQueryable source, [NotNull]
675675
/// </example>
676676
[PublicAPI]
677677
public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] ParsingConfig config, [NotNull] string keySelector, [NotNull] string resultSelector, object[] args)
678+
{
679+
return InternalGroupBy(source, config, keySelector, resultSelector, null, args);
680+
}
681+
682+
// NEED TEXT!
683+
public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] ParsingConfig config, [NotNull] string keySelector, [NotNull] string resultSelector, IEqualityComparer equalityComparer, object[] args)
684+
{
685+
return InternalGroupBy(source, config, keySelector, resultSelector, equalityComparer, args);
686+
}
687+
688+
internal static IQueryable InternalGroupBy([NotNull] IQueryable source, [NotNull] ParsingConfig config, [NotNull] string keySelector, [NotNull] string resultSelector, IEqualityComparer equalityComparer, object[] args)
678689
{
679690
Check.NotNull(source, nameof(source));
680691
Check.NotNull(config, nameof(config));
@@ -684,11 +695,24 @@ public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] Par
684695
bool createParameterCtor = config?.EvaluateGroupByAtDatabase ?? SupportsLinqToObjects(config, source);
685696
LambdaExpression keyLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, keySelector, args);
686697
LambdaExpression elementLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, resultSelector, args);
687-
688-
var optimized = OptimizeExpression(Expression.Call(
689-
typeof(Queryable), nameof(Queryable.GroupBy),
690-
new[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type },
691-
source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda)));
698+
699+
Expression optimized = null;
700+
if (equalityComparer == null)
701+
{
702+
optimized = OptimizeExpression(Expression.Call(
703+
typeof(Queryable), nameof(Queryable.GroupBy),
704+
new[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type },
705+
source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda)));
706+
}
707+
else
708+
{
709+
var equalityComparerGenericType = typeof(IEqualityComparer<>).MakeGenericType(keyLambda.Body.Type);
710+
optimized = OptimizeExpression(Expression.Call(
711+
typeof(Queryable), nameof(Queryable.GroupBy),
712+
new[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type },
713+
source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda),
714+
Expression.Constant(equalityComparer, equalityComparerGenericType)));
715+
}
692716

693717
return source.Provider.CreateQuery(optimized);
694718
}
@@ -700,6 +724,12 @@ public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] str
700724
return GroupBy(source, ParsingConfig.Default, keySelector, resultSelector, args);
701725
}
702726

727+
// NEED TEXT!
728+
public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] string keySelector, [NotNull] string resultSelector, IEqualityComparer equalityComparer, object[] args)
729+
{
730+
return GroupBy(source, ParsingConfig.Default, keySelector, resultSelector, equalityComparer, args);
731+
}
732+
703733
/// <summary>
704734
/// Groups the elements of a sequence according to a specified key string function
705735
/// and creates a result value from each group and its key.
@@ -717,7 +747,7 @@ public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] str
717747
/// </example>
718748
public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] ParsingConfig config, [NotNull] string keySelector, [NotNull] string resultSelector)
719749
{
720-
return GroupBy(source, config, keySelector, resultSelector, null);
750+
return GroupBy(source, config, keySelector, resultSelector, null, null);
721751
}
722752

723753
/// <inheritdoc cref="GroupBy(IQueryable, ParsingConfig, string, string)"/>
@@ -726,6 +756,18 @@ public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] str
726756
return GroupBy(source, ParsingConfig.Default, keySelector, resultSelector);
727757
}
728758

759+
// NEED TEXT!
760+
public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] ParsingConfig config, [NotNull] string keySelector, [NotNull] string resultSelector, IEqualityComparer equalityComparer)
761+
{
762+
return InternalGroupBy(source, config, keySelector, resultSelector, equalityComparer, null);
763+
}
764+
765+
// NEED TEXT!
766+
public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] string keySelector, [NotNull] string resultSelector, IEqualityComparer equalityComparer)
767+
{
768+
return GroupBy(source, ParsingConfig.Default, keySelector, resultSelector, equalityComparer);
769+
}
770+
729771
/// <summary>
730772
/// Groups the elements of a sequence according to a specified key string function
731773
/// and creates a result value from each group and its key.
@@ -743,6 +785,17 @@ public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] str
743785
/// </example>
744786
[PublicAPI]
745787
public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] ParsingConfig config, [NotNull] string keySelector, [CanBeNull] params object[] args)
788+
{
789+
return InternalGroupBy(source, config, keySelector, null, args);
790+
}
791+
792+
// NEED TEXT!
793+
public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] ParsingConfig config, [NotNull] string keySelector, IEqualityComparer equalityComparer, [CanBeNull] params object[] args)
794+
{
795+
return InternalGroupBy(source, config, keySelector, equalityComparer, args);
796+
}
797+
798+
internal static IQueryable InternalGroupBy([NotNull] IQueryable source, [NotNull] ParsingConfig config, [NotNull] string keySelector, IEqualityComparer equalityComparer, [CanBeNull] params object[] args)
746799
{
747800
Check.NotNull(source, nameof(source));
748801
Check.NotNull(config, nameof(config));
@@ -751,9 +804,22 @@ public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] Par
751804
bool createParameterCtor = config?.EvaluateGroupByAtDatabase ?? SupportsLinqToObjects(config, source);
752805
LambdaExpression keyLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, keySelector, args);
753806

754-
var optimized = OptimizeExpression(Expression.Call(
755-
typeof(Queryable), nameof(Queryable.GroupBy),
756-
new[] { source.ElementType, keyLambda.Body.Type }, source.Expression, Expression.Quote(keyLambda)));
807+
Expression optimized = null;
808+
809+
if (equalityComparer == null)
810+
{
811+
optimized = OptimizeExpression(Expression.Call(
812+
typeof(Queryable), nameof(Queryable.GroupBy),
813+
new[] { source.ElementType, keyLambda.Body.Type }, source.Expression, Expression.Quote(keyLambda)));
814+
}
815+
else
816+
{
817+
var equalityComparerGenericType = typeof(IEqualityComparer<>).MakeGenericType(keyLambda.Body.Type);
818+
optimized = OptimizeExpression(Expression.Call(
819+
typeof(Queryable), nameof(Queryable.GroupBy),
820+
new[] { source.ElementType, keyLambda.Body.Type }, source.Expression, Expression.Quote(keyLambda),
821+
Expression.Constant(equalityComparer, equalityComparerGenericType)));
822+
}
757823

758824
return source.Provider.CreateQuery(optimized);
759825
}
@@ -764,6 +830,13 @@ public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] str
764830
{
765831
return GroupBy(source, ParsingConfig.Default, keySelector, args);
766832
}
833+
834+
// NEED TEXT!
835+
public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] string keySelector, IEqualityComparer equalityComparer, [CanBeNull] params object[] args)
836+
{
837+
return GroupBy(source, ParsingConfig.Default, keySelector, equalityComparer, args);
838+
}
839+
767840
#endregion GroupBy
768841

769842
#region GroupByMany
@@ -1322,6 +1395,12 @@ public static IOrderedQueryable OrderBy([NotNull] this IQueryable source, [NotNu
13221395
return InternalOrderBy(source, config, ordering, null, args);
13231396
}
13241397

1398+
// NEED TEXT!
1399+
public static IOrderedQueryable OrderBy([NotNull] this IQueryable source, [NotNull] ParsingConfig config, [NotNull] string ordering, IComparer comparer, params object[] args)
1400+
{
1401+
return InternalOrderBy(source, config, ordering, comparer, args);
1402+
}
1403+
13251404
internal static IOrderedQueryable InternalOrderBy([NotNull] IQueryable source, [NotNull] ParsingConfig config, [NotNull] string ordering, IComparer comparer, params object[] args)
13261405
{
13271406
Check.NotNull(source, nameof(source));
@@ -1362,6 +1441,12 @@ internal static IOrderedQueryable InternalOrderBy([NotNull] IQueryable source, [
13621441
public static IOrderedQueryable OrderBy([NotNull] this IQueryable source, [NotNull] string ordering, params object[] args)
13631442
{
13641443
return OrderBy(source, ParsingConfig.Default, ordering, args);
1444+
}
1445+
1446+
// NEED TEXT!
1447+
public static IOrderedQueryable OrderBy([NotNull] this IQueryable source, [NotNull] string ordering, IComparer comparer, params object[] args)
1448+
{
1449+
return OrderBy(source, ParsingConfig.Default, ordering, comparer, args);
13651450
}
13661451

13671452
#endregion OrderBy
@@ -2272,7 +2357,13 @@ public static IOrderedQueryable ThenBy([NotNull] this IOrderedQueryable source,
22722357
return InternalThenBy(source, config, ordering, null, args);
22732358
}
22742359

2275-
internal static IOrderedQueryable InternalThenBy([NotNull] this IOrderedQueryable source, [NotNull] ParsingConfig config, [NotNull] string ordering, IComparer comparer, params object[] args)
2360+
// NEED TEXT!
2361+
public static IOrderedQueryable ThenBy([NotNull] this IOrderedQueryable source, [NotNull] ParsingConfig config, [NotNull] string ordering, IComparer comparer, params object[] args)
2362+
{
2363+
return InternalThenBy(source, config, ordering, comparer, args);
2364+
}
2365+
2366+
internal static IOrderedQueryable InternalThenBy([NotNull] IOrderedQueryable source, [NotNull] ParsingConfig config, [NotNull] string ordering, IComparer comparer, params object[] args)
22762367
{
22772368
Check.NotNull(source, nameof(source));
22782369
Check.NotNull(config, nameof(config));
@@ -2314,6 +2405,12 @@ public static IOrderedQueryable ThenBy([NotNull] this IOrderedQueryable source,
23142405
return ThenBy(source, ParsingConfig.Default, ordering, args);
23152406
}
23162407

2408+
// NEED TEXT!
2409+
public static IOrderedQueryable ThenBy([NotNull] this IOrderedQueryable source, [NotNull] string ordering, IComparer comparer, params object[] args)
2410+
{
2411+
return ThenBy(source, ParsingConfig.Default, ordering, comparer, args);
2412+
}
2413+
23172414
#endregion OrderBy
23182415

23192416
#region Where
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Globalization;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using NFluent;
8+
using Xunit;
9+
10+
namespace System.Linq.Dynamic.Core.Tests.MikArea
11+
{
12+
13+
public class Comparer
14+
{
15+
public class Customer
16+
{
17+
public string City { get; set; }
18+
public List<Order> Orders { get; set; }
19+
public string CompanyName { get; set; }
20+
public string Phone { get; set; }
21+
}
22+
public class Order
23+
{
24+
}
25+
26+
[Fact]
27+
public void Comparer_OrderBy_And_ThenBy()
28+
{
29+
List<Customer> customers = new List<Customer>() { new Customer() { CompanyName = "Ååå"} ,
30+
new Customer() { CompanyName = "Bbb" } ,
31+
new Customer() { CompanyName = "Ååå" } ,
32+
new Customer() { CompanyName = "Bbb" } ,
33+
new Customer() { CompanyName = "Aaa" },
34+
new Customer() { CompanyName = "Aaa" },
35+
};
36+
37+
CultureInfo culture = new CultureInfo("nb-NO");
38+
var test1 = customers.AsQueryable().OrderBy(x => x.CompanyName, StringComparer.Create(culture, true)).ToList();
39+
var test2 = customers.AsQueryable().OrderBy(x => x.CompanyName).ToList();
40+
var test3 = customers.AsQueryable().OrderBy(x => x.City).ThenBy(x => x.CompanyName, StringComparer.Create(culture, true)).ToList();
41+
var test2_V2 = customers.AsQueryable()
42+
.OrderBy("CompanyName");
43+
var test3_V2 = customers.AsQueryable()
44+
.OrderBy("City").ThenBy("CompanyName", StringComparer.Create(culture, true));
45+
var test1_V2 = customers.AsQueryable()
46+
.OrderBy("CompanyName", StringComparer.Create(culture, true));
47+
48+
for (int i = 0; i < test2.Count; i++)
49+
{
50+
Check.That(test2.ElementAt(i).CompanyName).IsEqualTo(test2_V2.ElementAt(i).CompanyName);
51+
}
52+
for (int i = 0; i < test1.Count; i++)
53+
{
54+
Check.That(test1.ElementAt(i).CompanyName).IsEqualTo(test1_V2.ElementAt(i).CompanyName);
55+
}
56+
for (int i = 0; i < test3.Count; i++)
57+
{
58+
Check.That(test3.ElementAt(i).CompanyName).IsEqualTo(test3_V2.ElementAt(i).CompanyName);
59+
}
60+
}
61+
62+
[Fact]
63+
public void Comparer_GroupBy()
64+
{
65+
List<Customer> customers = new List<Customer>() { new Customer() { City = "ZZZ" }, new Customer() { City = "ZzZ" } };
66+
var check = customers.GroupBy(x => x.City, StringComparer.InvariantCultureIgnoreCase).ToList();
67+
var check2 = customers.GroupBy(x => x.City,x => new { Name = x.CompanyName, Phone = x.Phone }, StringComparer.InvariantCultureIgnoreCase).ToList();
68+
var check3 = customers.GroupBy(x => x.City, x => new { Name = x.CompanyName, Phone = x.Phone }).ToList();
69+
70+
var check_V2 = customers.AsQueryable().GroupBy("City", StringComparer.InvariantCultureIgnoreCase);
71+
var check2_V2 = customers.AsQueryable().GroupBy("City", "new(CompanyName as Name, Phone)", StringComparer.InvariantCultureIgnoreCase);
72+
var check3_V2 = customers.AsQueryable().GroupBy("City", "new(CompanyName as Name, Phone)");
73+
74+
Check.That(check.Count).IsEqualTo(check_V2.Count());
75+
Check.That(check2.Count).IsEqualTo(check2_V2.Count());
76+
Check.That(check3.Count).IsEqualTo(check3_V2.Count());
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)