Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace System.Collections.Generic
- {
- using System;
- using System.Threading;
- using System.Threading.Tasks;
- /// <summary>
- /// A wrapper for a paginated, asynchronous enumerator.
- /// </summary>
- /// <typeparam name="T">the enumeration type</typeparam>
- public sealed class PaginatedEnumerator<T> : IAsyncEnumerator<T>
- {
- private readonly Func<int, Task<T[]>> _pageFunc;
- private T[] _pageItems;
- private int _position;
- /// <summary>
- /// Initializes a new instance of the <see cref="PaginatedEnumerator{T}"/> class.
- /// </summary>
- /// <param name="pageFunc">the callback for asynchronously retrieving the page entries</param>
- public PaginatedEnumerator(Func<int, Task<T[]>> pageFunc)
- => _pageFunc = pageFunc ?? throw new ArgumentNullException(nameof(pageFunc));
- /// <summary>
- /// Gets the current item.
- /// </summary>
- public T Current { get; private set; }
- /// <summary>
- /// Gets the number of the current page.
- /// </summary>
- public int CurrentPage { get; internal set; }
- /// <summary>
- /// Gets a value indicating whether the end has been reached.
- /// </summary>
- public bool HasReachedEnd { get; private set; }
- /// <summary>
- /// Gets a value indicating whether any items are available or whether the next page
- /// should be requested.
- /// </summary>
- public bool ItemsAvailable => _pageItems != null && _position < _pageItems.Length && !HasReachedEnd;
- /// <summary>
- /// Gets the number of items remaining in the current page.
- /// </summary>
- public int ItemsRemaining => ItemsAvailable ? _pageItems.Length - _position : 0;
- /// <summary>
- /// Gets the number of items the current page contains.
- /// </summary>
- public int PageItemCount => _pageItems == null ? 0 : _pageItems.Length;
- /// <summary>
- /// Does absolutely nothing.
- /// </summary>
- public void Dispose()
- {
- }
- /// <summary>
- /// Moves to the next item asynchronously.
- /// </summary>
- /// <param name="cancellationToken">
- /// a cancellation token used to propagate notification that the asynchronous operation
- /// should be canceled.
- /// </param>
- /// <returns>
- /// a task that represents the asynchronous operation. The task result is a value
- /// indicating whether an item could be get.
- /// </returns>
- public async Task<bool> MoveNext(CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
- // check if the enumerator end has been reached and no more pages are available to enumerate.
- if (HasReachedEnd)
- {
- return false;
- }
- // check if the end of the page was reached.
- if (_pageItems == null || _position >= _pageItems.Length)
- {
- // request the next page
- _pageItems = await _pageFunc(CurrentPage++);
- // check if no more items are available
- if (_pageItems == null || _pageItems.Length == 0)
- {
- // set the flag to indicate that the end has been reached.
- HasReachedEnd = true;
- // no items are available
- return false;
- }
- // reset position
- _position = 0;
- }
- // increase item position
- Current = _pageItems[_position++];
- return true;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement