-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCustomPaginator.cs
146 lines (127 loc) · 4.6 KB
/
CustomPaginator.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
using System.Runtime.CompilerServices;
using SpotifyAPI.Web;
using SpotifyAPI.Web.Http;
namespace SpotiSharpBackend;
// This is a slightly modified version of the default SimplePaginator (delays have been added) more to that under https://johnnycrazy.github.io/SpotifyAPI-NET/docs/pagination
public class CustomPaginator : IPaginator
{
protected virtual Task<bool> ShouldContinue<T>(List<T> results, IPaginatable<T> page)
{
return Task.FromResult(true);
}
protected virtual Task<bool> ShouldContinue<T, TNext>(List<T> results, IPaginatable<T, TNext> page)
{
return Task.FromResult(true);
}
public async Task<IList<T>> PaginateAll<T>(IPaginatable<T> firstPage, IAPIConnector connector, CancellationToken cancel = default)
{
Ensure.ArgumentNotNull(firstPage, nameof(firstPage));
Ensure.ArgumentNotNull(connector, nameof(connector));
var page = firstPage;
var results = new List<T>();
if (page.Items != null)
{
results.AddRange(page.Items);
}
while (page.Next != null && await ShouldContinue(results, page).ConfigureAwait(false))
{
page = await connector.Get<Paging<T>>(new Uri(page.Next, UriKind.Absolute), cancel).ConfigureAwait(false);
if (page.Items != null)
{
results.AddRange(page.Items);
}
await Task.Delay(100, cancel);
}
return results;
}
public async Task<IList<T>> PaginateAll<T, TNext>(
IPaginatable<T, TNext> firstPage, Func<TNext, IPaginatable<T, TNext>> mapper, IAPIConnector connector,
CancellationToken cancel = default
)
{
Ensure.ArgumentNotNull(firstPage, nameof(firstPage));
Ensure.ArgumentNotNull(mapper, nameof(mapper));
Ensure.ArgumentNotNull(connector, nameof(connector));
var page = firstPage;
var results = new List<T>();
if (page.Items != null)
{
results.AddRange(page.Items);
}
while (page.Next != null && await ShouldContinue(results, page).ConfigureAwait(false))
{
var next = await connector.Get<TNext>(new Uri(page.Next, UriKind.Absolute), cancel).ConfigureAwait(false);
page = mapper(next);
if (page.Items != null)
{
results.AddRange(page.Items);
}
await Task.Delay(100, cancel);
}
return results;
}
public async IAsyncEnumerable<T> Paginate<T>(
IPaginatable<T> firstPage,
IAPIConnector connector,
[EnumeratorCancellation] CancellationToken cancel = default)
{
Ensure.ArgumentNotNull(firstPage, nameof(firstPage));
Ensure.ArgumentNotNull(connector, nameof(connector));
if (firstPage.Items == null)
{
throw new ArgumentException("The first page has to contain an Items list!", nameof(firstPage));
}
var page = firstPage;
foreach (var item in page.Items)
{
yield return item;
}
while (page.Next != null)
{
page = await connector.Get<Paging<T>>(new Uri(page.Next, UriKind.Absolute), cancel).ConfigureAwait(false);
foreach (var item in page.Items!)
{
yield return item;
}
}
}
public async IAsyncEnumerable<T> Paginate<T, TNext>(
IPaginatable<T, TNext> firstPage,
Func<TNext, IPaginatable<T, TNext>> mapper,
IAPIConnector connector,
[EnumeratorCancellation] CancellationToken cancel = default)
{
Ensure.ArgumentNotNull(firstPage, nameof(firstPage));
Ensure.ArgumentNotNull(mapper, nameof(mapper));
Ensure.ArgumentNotNull(connector, nameof(connector));
if (firstPage.Items == null)
{
throw new ArgumentException("The first page has to contain an Items list!", nameof(firstPage));
}
var page = firstPage;
foreach (var item in page.Items)
{
yield return item;
}
while (page.Next != null)
{
var next = await connector.Get<TNext>(new Uri(page.Next, UriKind.Absolute), cancel).ConfigureAwait(false);
page = mapper(next);
foreach (var item in page.Items!)
{
yield return item;
}
}
}
private static class Ensure
{
public static void ArgumentNotNull(object value, string name)
{
if (value != null)
{
return;
}
throw new ArgumentNullException(name);
}
}
}