Skip to content

Commit f2521c6

Browse files
committed
Refactored DataLoader
1 parent ba4a210 commit f2521c6

File tree

46 files changed

+1430
-561
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1430
-561
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
using System.Linq.Expressions;
2+
3+
namespace GreenDonut.Data;
4+
5+
internal static class DataStateHelper
6+
{
7+
internal static IDataLoader CreateBranch<TKey, TValue>(
8+
string branchKey,
9+
IDataLoader<TKey, TValue> dataLoader,
10+
QueryState state)
11+
where TKey : notnull
12+
{
13+
var branch = new QueryDataLoader<TKey, TValue>(
14+
(DataLoaderBase<TKey, TValue>)dataLoader,
15+
branchKey);
16+
branch.SetState(state.Key, state.Value);
17+
return branch;
18+
}
19+
20+
internal static IDataLoader CreateBranch<TKey, TValue, TElement>(
21+
string branchKey,
22+
IDataLoader<TKey, TValue> dataLoader,
23+
QueryContext<TElement> state)
24+
where TKey : notnull
25+
{
26+
var branch = new QueryDataLoader<TKey, TValue>(
27+
(DataLoaderBase<TKey, TValue>)dataLoader,
28+
branchKey);
29+
30+
if (state.Selector is not null)
31+
{
32+
branch.SetState(DataStateKeys.Selector, state.Selector);
33+
}
34+
35+
if (state.Predicate is not null)
36+
{
37+
branch.SetState(DataStateKeys.Predicate, state.Predicate);
38+
}
39+
40+
if (state.Sorting is not null)
41+
{
42+
branch.SetState(DataStateKeys.Sorting, state.Sorting);
43+
}
44+
45+
return branch;
46+
}
47+
48+
internal static string ComputeHash<TValue>(this QueryContext<TValue> state)
49+
{
50+
var hasher = ExpressionHasherPool.Shared.Get();
51+
52+
if (state.Selector is not null)
53+
{
54+
hasher.Add(state.Selector);
55+
}
56+
57+
if (state.Predicate is not null)
58+
{
59+
hasher.Add(state.Predicate);
60+
}
61+
62+
if (state.Sorting is not null)
63+
{
64+
hasher.Add(state.Sorting);
65+
}
66+
67+
var hash = hasher.Compute();
68+
ExpressionHasherPool.Shared.Return(hasher);
69+
return hash;
70+
}
71+
72+
internal static ExpressionHasher Add<TValue>(this ExpressionHasher hasher, QueryContext<TValue> state)
73+
{
74+
if (state.Selector is not null)
75+
{
76+
hasher.Add(state.Selector);
77+
}
78+
79+
if (state.Predicate is not null)
80+
{
81+
hasher.Add(state.Predicate);
82+
}
83+
84+
if (state.Sorting is not null)
85+
{
86+
hasher.Add(state.Sorting);
87+
}
88+
89+
return hasher;
90+
}
91+
92+
public static string ComputeHash(this Expression expression)
93+
{
94+
var hasher = ExpressionHasherPool.Shared.Get();
95+
var branchKey = hasher.Add(expression).Compute();
96+
ExpressionHasherPool.Shared.Return(hasher);
97+
return branchKey;
98+
}
99+
100+
public static string ComputeHash<T>(this SortDefinition<T> sortDefinition)
101+
{
102+
var hasher = ExpressionHasherPool.Shared.Get();
103+
var branchKey = hasher.Add(sortDefinition).Compute();
104+
ExpressionHasherPool.Shared.Return(hasher);
105+
return branchKey;
106+
}
107+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace GreenDonut.Data;
2+
3+
public static class DataStateKeys
4+
{
5+
public const string Selector = "GreenDonut.Data.Selector";
6+
public const string Predicate = "GreenDonut.Data.Predicate";
7+
public const string Sorting = "GreenDonut.Data.Sorting";
8+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System.Collections.Immutable;
2+
using System.Linq.Expressions;
3+
4+
namespace GreenDonut.Data;
5+
6+
/// <summary>
7+
/// A default implementation of the <see cref="IPredicateBuilder"/>.
8+
/// </summary>
9+
public sealed class DefaultPredicateBuilder : IPredicateBuilder
10+
{
11+
private ImmutableArray<LambdaExpression> _predicates = ImmutableArray<LambdaExpression>.Empty;
12+
13+
/// <summary>
14+
/// Initializes a new instance of <see cref="DefaultPredicateBuilder"/>.
15+
/// </summary>
16+
/// <param name="initialPredicate">
17+
/// The initial predicate to add.
18+
/// </param>
19+
public DefaultPredicateBuilder(LambdaExpression? initialPredicate)
20+
{
21+
if(initialPredicate is not null)
22+
{
23+
_predicates = _predicates.Add(initialPredicate);
24+
}
25+
}
26+
27+
private DefaultPredicateBuilder(ImmutableArray<LambdaExpression> predicates)
28+
{
29+
_predicates = predicates;
30+
}
31+
32+
/// <inheritdoc />
33+
public void Add<T>(Expression<Func<T, bool>> selector)
34+
{
35+
if (!_predicates.Contains(selector))
36+
{
37+
_predicates = _predicates.Add(selector);
38+
}
39+
}
40+
41+
/// <inheritdoc />
42+
public Expression<Func<T, bool>>? TryCompile<T>()
43+
{
44+
if (_predicates.Length == 0)
45+
{
46+
return null;
47+
}
48+
49+
if (_predicates.Length == 1)
50+
{
51+
return (Expression<Func<T, bool>>)_predicates[0];
52+
}
53+
54+
if (_predicates.Length == 2)
55+
{
56+
return ExpressionHelpers.And(
57+
(Expression<Func<T, bool>>)_predicates[0],
58+
(Expression<Func<T, bool>>)_predicates[1]);
59+
}
60+
61+
var expression = (Expression<Func<T, bool>>)_predicates[0];
62+
for (var i = 1; i < _predicates.Length; i++)
63+
{
64+
expression = ExpressionHelpers.And(
65+
expression,
66+
(Expression<Func<T, bool>>)_predicates[i]);
67+
}
68+
69+
return expression;
70+
}
71+
72+
public DefaultPredicateBuilder Branch()
73+
=> new(_predicates);
74+
75+
public static DefaultPredicateBuilder Empty { get; } = new(ImmutableArray<LambdaExpression>.Empty);
76+
}
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,59 @@
1-
using System.Diagnostics.CodeAnalysis;
1+
using System.Collections.Immutable;
22
using System.Linq.Expressions;
33

4-
namespace GreenDonut.Selectors;
4+
namespace GreenDonut.Data;
55

66
/// <summary>
77
/// A default implementation of the <see cref="ISelectorBuilder"/>.
88
/// </summary>
9-
[Experimental(Experiments.Selectors)]
109
public sealed class DefaultSelectorBuilder : ISelectorBuilder
1110
{
12-
private List<LambdaExpression>? _selectors;
11+
private ImmutableArray<LambdaExpression> _selectors = ImmutableArray<LambdaExpression>.Empty;
12+
13+
public DefaultSelectorBuilder(LambdaExpression? initialSelector = null)
14+
{
15+
if (initialSelector is not null)
16+
{
17+
_selectors = _selectors.Add(initialSelector);
18+
}
19+
}
20+
21+
private DefaultSelectorBuilder(ImmutableArray<LambdaExpression> selectors)
22+
{
23+
_selectors = selectors;
24+
}
1325

1426
/// <inheritdoc />
1527
public void Add<T>(Expression<Func<T, T>> selector)
1628
{
17-
_selectors ??= new List<LambdaExpression>();
1829
if (!_selectors.Contains(selector))
1930
{
20-
_selectors.Add(selector);
31+
_selectors = _selectors.Add(selector);
2132
}
2233
}
2334

2435
/// <inheritdoc />
2536
public Expression<Func<T, T>>? TryCompile<T>()
2637
{
27-
if (_selectors is null)
38+
if (_selectors.Length == 0)
2839
{
2940
return null;
3041
}
3142

32-
if (_selectors.Count == 1)
43+
if (_selectors.Length == 1)
3344
{
3445
return (Expression<Func<T, T>>)_selectors[0];
3546
}
3647

37-
if (_selectors.Count == 2)
48+
if (_selectors.Length == 2)
3849
{
3950
return ExpressionHelpers.Combine(
4051
(Expression<Func<T, T>>)_selectors[0],
4152
(Expression<Func<T, T>>)_selectors[1]);
4253
}
4354

4455
var expression = (Expression<Func<T, T>>)_selectors[0];
45-
for (var i = 1; i < _selectors.Count; i++)
56+
for (var i = 1; i < _selectors.Length; i++)
4657
{
4758
expression = ExpressionHelpers.Combine(
4859
expression,
@@ -51,4 +62,9 @@ public void Add<T>(Expression<Func<T, T>> selector)
5162

5263
return expression;
5364
}
65+
66+
public DefaultSelectorBuilder Branch()
67+
=> new(_selectors);
68+
69+
public static DefaultSelectorBuilder Empty { get; } = new(ImmutableArray<LambdaExpression>.Empty);
5470
}

0 commit comments

Comments
 (0)