Skip to content

Commit c48648c

Browse files
committed
Some more refactoring
1 parent ca61485 commit c48648c

4 files changed

Lines changed: 80 additions & 68 deletions

File tree

Common.Tests/Query/DBExpressionBuilderTests.cs renamed to Common.Tests/Query/ExpressionBuilderTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace OpenShock.Common.Tests.Query;
88

9-
public class DBExpressionBuilderTests
9+
public class ExpressionBuilderTests
1010
{
1111
public sealed class TestClass
1212
{
@@ -30,7 +30,7 @@ public enum TestEnum
3030

3131
private readonly TestClass[] TestArray;
3232

33-
public DBExpressionBuilderTests()
33+
public ExpressionBuilderTests()
3434
{
3535
var faker = new Faker<TestClass>()
3636
.UseSeed(12345)

Common/Extensions/IQueryableExtensions.cs

Lines changed: 2 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,57 +8,6 @@ namespace OpenShock.Common.Extensions;
88

99
public static class IQueryableExtensions
1010
{
11-
private static MethodInfo[] PublicQueryableMethods => typeof(Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public);
12-
private static readonly MethodInfo OrderByAscendingMethodInfo = PublicQueryableMethods.Single(m => m.Name == "OrderBy" && m.GetParameters().Length == 2);
13-
private static readonly MethodInfo OrderByDescendingMethodInfo = PublicQueryableMethods.Single(m => m.Name == "OrderByDescending" && m.GetParameters().Length == 2);
14-
private static readonly MethodInfo OrderThenByAscendingMethodInfo = PublicQueryableMethods.Single(m => m.Name == "ThenBy" && m.GetParameters().Length == 2);
15-
private static readonly MethodInfo OrderThenByDescendingMethodInfo = PublicQueryableMethods.Single(m => m.Name == "ThenByDescending" && m.GetParameters().Length == 2);
16-
17-
private record struct OrderByItem(string Name, bool Descending);
18-
19-
private static OrderByItem ParseOrderByPart(string str)
20-
{
21-
var parts = str.Split(' ');
22-
if (parts.Length == 1)
23-
{
24-
return new OrderByItem(str, false);
25-
}
26-
27-
if (parts.Length == 2)
28-
{
29-
bool descending = parts[1].ToLower() switch
30-
{
31-
"asc" => false,
32-
"desc" => true,
33-
_ => throw new InvalidOperationException("Direction if specified must be 'asc' or 'desc'."),
34-
};
35-
36-
return new OrderByItem(parts[0], descending);
37-
}
38-
39-
throw new InvalidOperationException("Invalid orderby query.");
40-
}
41-
42-
private static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, LambdaExpression keySelector, bool descending = false)
43-
{
44-
var method = (descending ? OrderByDescendingMethodInfo : OrderByAscendingMethodInfo)
45-
.MakeGenericMethod(typeof(T), keySelector.Body.Type);
46-
47-
var call = Expression.Call(null, method, source.Expression, Expression.Quote(keySelector));
48-
49-
return (IOrderedQueryable<T>)source.Provider.CreateQuery(call);
50-
}
51-
52-
private static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, LambdaExpression keySelector, bool descending = false)
53-
{
54-
var method = (descending ? OrderThenByDescendingMethodInfo : OrderThenByAscendingMethodInfo)
55-
.MakeGenericMethod(typeof(T), keySelector.Body.Type);
56-
57-
var call = Expression.Call(null, method, source.Expression, Expression.Quote(keySelector));
58-
59-
return (IOrderedQueryable<T>)source.Provider.CreateQuery(call);
60-
}
61-
6211
public static IQueryable<TEntity> WhereUserIdMatches<TEntity>(this IQueryable<TEntity> source, Expression<Func<TEntity, User>> userNavigation, Guid userId)
6312
{
6413
var userIdConstant = Expression.Constant(userId);
@@ -88,21 +37,10 @@ public static IQueryable<T> ApplyFilter<T>(this IQueryable<T> query, string filt
8837
return query.Where(DBExpressionBuilder.GetFilterExpression<T>(filterQuery));
8938
}
9039

91-
public static IOrderedQueryable<T> ApplyOrderBy<T>(this IQueryable<T> query, string orderbyQuery) where T : class
40+
public static IOrderedQueryable<T> ApplyOrderBy<T>(IQueryable<T> query, string orderbyQuery) where T : class
9241
{
9342
ArgumentException.ThrowIfNullOrWhiteSpace(orderbyQuery, nameof(orderbyQuery));
9443

95-
var parts = orderbyQuery.Split(',');
96-
97-
var parsed = ParseOrderByPart(parts[0]);
98-
var orderedQuery = query.OrderBy(DBExpressionBuilderUtils.CreatePropertyOrFieldAccessorExpression<T>(parsed.Name), parsed.Descending);
99-
100-
for (int i = 1; i < parts.Length; ++i)
101-
{
102-
parsed = ParseOrderByPart(parts[i]);
103-
orderedQuery = orderedQuery.ThenBy(DBExpressionBuilderUtils.CreatePropertyOrFieldAccessorExpression<T>(parsed.Name), parsed.Descending);
104-
}
105-
106-
return orderedQuery;
44+
return OrderByQueryBuilder.ApplyOrderBy(query, orderbyQuery);
10745
}
10846
}

Common/SignalRExtensions.cs renamed to Common/Extensions/ISignalRServerBuilderExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
using Microsoft.AspNetCore.SignalR;
22
using Microsoft.AspNetCore.SignalR.StackExchangeRedis;
33

4-
namespace OpenShock.Common;
4+
namespace OpenShock.Common.Extensions;
55

6-
public static class SignalRExtensions
6+
public static class ISignalRServerBuilderExtensions
77
{
88
/// <summary>
99
/// Adds scale-out to a <see cref="ISignalRServerBuilder"/>, using a shared Redis server.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System.Linq.Expressions;
2+
using System.Reflection;
3+
4+
namespace OpenShock.Common.Query;
5+
6+
public static class OrderByQueryBuilder
7+
{
8+
private static MethodInfo[] PublicQueryableMethods => typeof(Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public);
9+
private static readonly MethodInfo OrderByAscendingMethodInfo = PublicQueryableMethods.Single(m => m.Name == "OrderBy" && m.GetParameters().Length == 2);
10+
private static readonly MethodInfo OrderByDescendingMethodInfo = PublicQueryableMethods.Single(m => m.Name == "OrderByDescending" && m.GetParameters().Length == 2);
11+
private static readonly MethodInfo OrderThenByAscendingMethodInfo = PublicQueryableMethods.Single(m => m.Name == "ThenBy" && m.GetParameters().Length == 2);
12+
private static readonly MethodInfo OrderThenByDescendingMethodInfo = PublicQueryableMethods.Single(m => m.Name == "ThenByDescending" && m.GetParameters().Length == 2);
13+
14+
private record struct OrderByItem(string Name, bool Descending);
15+
16+
private static OrderByItem ParseOrderByPart(string str)
17+
{
18+
var parts = str.Split(' ');
19+
if (parts.Length == 1)
20+
{
21+
return new OrderByItem(str, false);
22+
}
23+
24+
if (parts.Length == 2)
25+
{
26+
bool descending = parts[1].ToLower() switch
27+
{
28+
"asc" => false,
29+
"desc" => true,
30+
_ => throw new InvalidOperationException("Direction if specified must be 'asc' or 'desc'."),
31+
};
32+
33+
return new OrderByItem(parts[0], descending);
34+
}
35+
36+
throw new InvalidOperationException("Invalid orderby query.");
37+
}
38+
39+
private static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, LambdaExpression keySelector, bool descending = false)
40+
{
41+
var method = (descending ? OrderByDescendingMethodInfo : OrderByAscendingMethodInfo)
42+
.MakeGenericMethod(typeof(T), keySelector.Body.Type);
43+
44+
var call = Expression.Call(null, method, source.Expression, Expression.Quote(keySelector));
45+
46+
return (IOrderedQueryable<T>)source.Provider.CreateQuery(call);
47+
}
48+
49+
private static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, LambdaExpression keySelector, bool descending = false)
50+
{
51+
var method = (descending ? OrderThenByDescendingMethodInfo : OrderThenByAscendingMethodInfo)
52+
.MakeGenericMethod(typeof(T), keySelector.Body.Type);
53+
54+
var call = Expression.Call(null, method, source.Expression, Expression.Quote(keySelector));
55+
56+
return (IOrderedQueryable<T>)source.Provider.CreateQuery(call);
57+
}
58+
59+
public static IOrderedQueryable<T> ApplyOrderBy<T>(this IQueryable<T> query, string orderbyQuery) where T : class
60+
{
61+
var parts = orderbyQuery.Split(',');
62+
63+
var parsed = ParseOrderByPart(parts[0]);
64+
var orderedQuery = query.OrderBy(DBExpressionBuilderUtils.CreatePropertyOrFieldAccessorExpression<T>(parsed.Name), parsed.Descending);
65+
66+
for (int i = 1; i < parts.Length; ++i)
67+
{
68+
parsed = ParseOrderByPart(parts[i]);
69+
orderedQuery = orderedQuery.ThenBy(DBExpressionBuilderUtils.CreatePropertyOrFieldAccessorExpression<T>(parsed.Name), parsed.Descending);
70+
}
71+
72+
return orderedQuery;
73+
}
74+
}

0 commit comments

Comments
 (0)