Added IPaginatble to also support Cursor based paging

This commit is contained in:
Jonas Dellinger 2020-06-13 12:55:48 +02:00
parent 5a9155056d
commit de98bc012f
8 changed files with 85 additions and 53 deletions

View File

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using SpotifyAPI.Web.Http;
using SpotifyAPI.Web;
namespace SpotifyAPI.Web
{
@ -18,7 +19,7 @@ namespace SpotifyAPI.Web
/// <param name="connector">An API Connector to make requests to spotify</param>
/// <typeparam name="T">Paging Type</typeparam>
/// <returns>A list containing all pages, including the firstPage</returns>
Task<IList<T>> PaginateAll<T>(Paging<T> firstPage, IAPIConnector connector);
Task<IList<T>> PaginateAll<T>(IPaginatable<T> firstPage, IAPIConnector connector);
/// <summary>
/// Fetches all pages and returns them grouped in a list.
@ -33,8 +34,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">Outer response Type</typeparam>
/// <returns>A list containing all pages, including the firstPage</returns>
Task<IList<T>> PaginateAll<T, TNext>(
Paging<T, TNext> firstPage,
Func<TNext, Paging<T, TNext>> mapper,
IPaginatable<T, TNext> firstPage,
Func<TNext, IPaginatable<T, TNext>> mapper,
IAPIConnector connector
);
@ -47,7 +48,7 @@ namespace SpotifyAPI.Web
/// <param name="cancel">A CancellationToken</param>
/// <typeparam name="T">Paging Type</typeparam>
/// <returns></returns>
IAsyncEnumerable<T> Paginate<T>(Paging<T> firstPage, IAPIConnector connector, CancellationToken cancel = default);
IAsyncEnumerable<T> Paginate<T>(IPaginatable<T> firstPage, IAPIConnector connector, CancellationToken cancel = default);
/// <summary>
/// Fetches all pages and returns them grouped in a list.
@ -63,8 +64,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">Outer response Type</typeparam>
/// <returns></returns>
IAsyncEnumerable<T> Paginate<T, TNext>(
Paging<T, TNext> firstPage,
Func<TNext, Paging<T, TNext>> mapper,
IPaginatable<T, TNext> firstPage,
Func<TNext, IPaginatable<T, TNext>> mapper,
IAPIConnector connector,
CancellationToken cancel = default
);

View File

@ -107,7 +107,7 @@ namespace SpotifyAPI.Web
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
/// <typeparam name="T">The Paging-Type</typeparam>
/// <returns>A list containing all fetched pages</returns>
Task<IList<T>> PaginateAll<T>(Paging<T> firstPage, IPaginator? paginator = default!);
Task<IList<T>> PaginateAll<T>(IPaginatable<T> firstPage, IPaginator? paginator = default!);
/// <summary>
/// Fetches all pages and returns them grouped in a list.
@ -118,7 +118,7 @@ namespace SpotifyAPI.Web
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
/// <typeparam name="T">The Paging-Type</typeparam>
/// <returns>A list containing all fetched pages</returns>
Task<IList<T>> PaginateAll<T>(Func<Task<Paging<T>>> getFirstPage, IPaginator? paginator = default!);
Task<IList<T>> PaginateAll<T>(Func<Task<IPaginatable<T>>> getFirstPage, IPaginator? paginator = default!);
/// <summary>
/// Fetches all pages and returns them grouped in a list.
@ -129,7 +129,7 @@ namespace SpotifyAPI.Web
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
/// <typeparam name="T">The Paging-Type</typeparam>
/// <returns>A list containing all fetched pages</returns>
Task<IList<T>> PaginateAll<T>(Task<Paging<T>> firstPageTask, IPaginator? paginator = default!);
Task<IList<T>> PaginateAll<T>(Task<IPaginatable<T>> firstPageTask, IPaginator? paginator = default!);
/// <summary>
/// Fetches all pages and returns them grouped in a list.
@ -145,8 +145,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">The Response-Type</typeparam>
/// <returns>A list containing all fetched pages</returns>
Task<IList<T>> PaginateAll<T, TNext>(
Paging<T, TNext> firstPage,
Func<TNext, Paging<T, TNext>> mapper,
IPaginatable<T, TNext> firstPage,
Func<TNext, IPaginatable<T, TNext>> mapper,
IPaginator? paginator = default!
);
@ -164,8 +164,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">The Response-Type</typeparam>
/// <returns></returns>
Task<IList<T>> PaginateAll<T, TNext>(
Func<Task<Paging<T, TNext>>> getFirstPage,
Func<TNext, Paging<T, TNext>> mapper,
Func<Task<IPaginatable<T, TNext>>> getFirstPage,
Func<TNext, IPaginatable<T, TNext>> mapper,
IPaginator? paginator = default!
);
@ -183,8 +183,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">The Response-Type</typeparam>
/// <returns></returns>
Task<IList<T>> PaginateAll<T, TNext>(
Task<Paging<T, TNext>> firstPageTask,
Func<TNext, Paging<T, TNext>> mapper,
Task<IPaginatable<T, TNext>> firstPageTask,
Func<TNext, IPaginatable<T, TNext>> mapper,
IPaginator? paginator = default!
);
@ -200,7 +200,7 @@ namespace SpotifyAPI.Web
/// <typeparam name="T">The Paging-Type</typeparam>
/// <returns>An iterable IAsyncEnumerable</returns>
IAsyncEnumerable<T> Paginate<T>(
Paging<T> firstPage,
IPaginatable<T> firstPage,
IPaginator? paginator = default!,
CancellationToken cancellationToken = default!
);
@ -216,7 +216,7 @@ namespace SpotifyAPI.Web
/// <typeparam name="T">The Paging-Type</typeparam>
/// <returns>An iterable IAsyncEnumerable</returns>
IAsyncEnumerable<T> Paginate<T>(
Func<Task<Paging<T>>> getFirstPage,
Func<Task<IPaginatable<T>>> getFirstPage,
IPaginator? paginator = default!,
CancellationToken cancellationToken = default!
);
@ -232,7 +232,7 @@ namespace SpotifyAPI.Web
/// <typeparam name="T">The Paging-Type</typeparam>
/// <returns>An iterable IAsyncEnumerable</returns>
IAsyncEnumerable<T> Paginate<T>(
Task<Paging<T>> firstPageTask,
Task<IPaginatable<T>> firstPageTask,
IPaginator? paginator = default!,
CancellationToken cancellationToken = default!
);
@ -252,8 +252,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">The Response-Type</typeparam>
/// <returns></returns>
IAsyncEnumerable<T> Paginate<T, TNext>(
Paging<T, TNext> firstPage,
Func<TNext, Paging<T, TNext>> mapper,
IPaginatable<T, TNext> firstPage,
Func<TNext, IPaginatable<T, TNext>> mapper,
IPaginator? paginator = default!,
CancellationToken cancellationToken = default!
);
@ -273,8 +273,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">The Response-Type</typeparam>
/// <returns></returns>
IAsyncEnumerable<T> Paginate<T, TNext>(
Func<Task<Paging<T, TNext>>> getFirstPage,
Func<TNext, Paging<T, TNext>> mapper,
Func<Task<IPaginatable<T, TNext>>> getFirstPage,
Func<TNext, IPaginatable<T, TNext>> mapper,
IPaginator? paginator = default!,
CancellationToken cancellationToken = default!
);
@ -294,8 +294,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">The Response-Type</typeparam>
/// <returns></returns>
IAsyncEnumerable<T> Paginate<T, TNext>(
Task<Paging<T, TNext>> firstPageTask,
Func<TNext, Paging<T, TNext>> mapper,
Task<IPaginatable<T, TNext>> firstPageTask,
Func<TNext, IPaginatable<T, TNext>> mapper,
IPaginator? paginator = default!,
CancellationToken cancellationToken = default!
);

View File

@ -9,16 +9,16 @@ namespace SpotifyAPI.Web
{
public class SimplePaginator : IPaginator
{
protected virtual Task<bool> ShouldContinue<T>(List<T> results, Paging<T> page)
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, Paging<T, TNext> page)
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>(Paging<T> firstPage, IAPIConnector connector)
public async Task<IList<T>> PaginateAll<T>(IPaginatable<T> firstPage, IAPIConnector connector)
{
Ensure.ArgumentNotNull(firstPage, nameof(firstPage));
Ensure.ArgumentNotNull(connector, nameof(connector));
@ -36,7 +36,7 @@ namespace SpotifyAPI.Web
}
public async Task<IList<T>> PaginateAll<T, TNext>(
Paging<T, TNext> firstPage, Func<TNext, Paging<T, TNext>> mapper, IAPIConnector connector
IPaginatable<T, TNext> firstPage, Func<TNext, IPaginatable<T, TNext>> mapper, IAPIConnector connector
)
{
Ensure.ArgumentNotNull(firstPage, nameof(firstPage));
@ -58,7 +58,7 @@ namespace SpotifyAPI.Web
#if NETSTANDARD2_1
public async IAsyncEnumerable<T> Paginate<T>(
Paging<T> firstPage,
IPaginatable<T> firstPage,
IAPIConnector connector,
[EnumeratorCancellation] CancellationToken cancel = default)
{
@ -81,8 +81,8 @@ namespace SpotifyAPI.Web
}
public async IAsyncEnumerable<T> Paginate<T, TNext>(
Paging<T, TNext> firstPage,
Func<TNext, Paging<T, TNext>> mapper,
IPaginatable<T, TNext> firstPage,
Func<TNext, IPaginatable<T, TNext>> mapper,
IAPIConnector connector,
[EnumeratorCancellation] CancellationToken cancel = default)
{

View File

@ -91,7 +91,7 @@ namespace SpotifyAPI.Web
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
/// <typeparam name="T">The Paging-Type</typeparam>
/// <returns>A list containing all fetched pages</returns>
public Task<IList<T>> PaginateAll<T>(Paging<T> firstPage, IPaginator? paginator = null)
public Task<IList<T>> PaginateAll<T>(IPaginatable<T> firstPage, IPaginator? paginator = null)
{
return (paginator ?? DefaultPaginator).PaginateAll(firstPage, _apiConnector);
}
@ -105,7 +105,7 @@ namespace SpotifyAPI.Web
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
/// <typeparam name="T">The Paging-Type</typeparam>
/// <returns>A list containing all fetched pages</returns>
public async Task<IList<T>> PaginateAll<T>(Func<Task<Paging<T>>> getFirstPage, IPaginator? paginator = null)
public async Task<IList<T>> PaginateAll<T>(Func<Task<IPaginatable<T>>> getFirstPage, IPaginator? paginator = null)
{
Ensure.ArgumentNotNull(getFirstPage, nameof(getFirstPage));
@ -122,7 +122,7 @@ namespace SpotifyAPI.Web
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
/// <typeparam name="T">The Paging-Type</typeparam>
/// <returns>A list containing all fetched pages</returns>
public async Task<IList<T>> PaginateAll<T>(Task<Paging<T>> firstPageTask, IPaginator? paginator = null)
public async Task<IList<T>> PaginateAll<T>(Task<IPaginatable<T>> firstPageTask, IPaginator? paginator = null)
{
Ensure.ArgumentNotNull(firstPageTask, nameof(firstPageTask));
@ -145,8 +145,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">The Response-Type</typeparam>
/// <returns>A list containing all fetched pages</returns>
public Task<IList<T>> PaginateAll<T, TNext>(
Paging<T, TNext> firstPage,
Func<TNext, Paging<T, TNext>> mapper,
IPaginatable<T, TNext> firstPage,
Func<TNext, IPaginatable<T, TNext>> mapper,
IPaginator? paginator = null
)
{
@ -168,8 +168,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">The Response-Type</typeparam>
/// <returns></returns>
public async Task<IList<T>> PaginateAll<T, TNext>(
Func<Task<Paging<T, TNext>>> getFirstPage,
Func<TNext, Paging<T, TNext>> mapper,
Func<Task<IPaginatable<T, TNext>>> getFirstPage,
Func<TNext, IPaginatable<T, TNext>> mapper,
IPaginator? paginator = null
)
{
@ -193,8 +193,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">The Response-Type</typeparam>
/// <returns></returns>
public async Task<IList<T>> PaginateAll<T, TNext>(
Task<Paging<T, TNext>> firstPageTask,
Func<TNext, Paging<T, TNext>> mapper,
Task<IPaginatable<T, TNext>> firstPageTask,
Func<TNext, IPaginatable<T, TNext>> mapper,
IPaginator? paginator = null
)
{
@ -217,7 +217,7 @@ namespace SpotifyAPI.Web
/// <typeparam name="T">The Paging-Type</typeparam>
/// <returns>An iterable IAsyncEnumerable</returns>
public IAsyncEnumerable<T> Paginate<T>(
Paging<T> firstPage,
IPaginatable<T> firstPage,
IPaginator? paginator = null,
CancellationToken cancellationToken = default
)
@ -236,7 +236,7 @@ namespace SpotifyAPI.Web
/// <typeparam name="T">The Paging-Type</typeparam>
/// <returns>An iterable IAsyncEnumerable</returns>
public async IAsyncEnumerable<T> Paginate<T>(
Func<Task<Paging<T>>> getFirstPage,
Func<Task<IPaginatable<T>>> getFirstPage,
IPaginator? paginator = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default
)
@ -265,7 +265,7 @@ namespace SpotifyAPI.Web
/// <typeparam name="T">The Paging-Type</typeparam>
/// <returns>An iterable IAsyncEnumerable</returns>
public async IAsyncEnumerable<T> Paginate<T>(
Task<Paging<T>> firstPageTask,
Task<IPaginatable<T>> firstPageTask,
IPaginator? paginator = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
@ -296,8 +296,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">The Response-Type</typeparam>
/// <returns></returns>
public IAsyncEnumerable<T> Paginate<T, TNext>(
Paging<T, TNext> firstPage,
Func<TNext, Paging<T, TNext>> mapper,
IPaginatable<T, TNext> firstPage,
Func<TNext, IPaginatable<T, TNext>> mapper,
IPaginator? paginator = null,
CancellationToken cancellationToken = default
)
@ -320,8 +320,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">The Response-Type</typeparam>
/// <returns></returns>
public async IAsyncEnumerable<T> Paginate<T, TNext>(
Func<Task<Paging<T, TNext>>> getFirstPage,
Func<TNext, Paging<T, TNext>> mapper,
Func<Task<IPaginatable<T, TNext>>> getFirstPage,
Func<TNext, IPaginatable<T, TNext>> mapper,
IPaginator? paginator = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
@ -352,8 +352,8 @@ namespace SpotifyAPI.Web
/// <typeparam name="TNext">The Response-Type</typeparam>
/// <returns></returns>
public async IAsyncEnumerable<T> Paginate<T, TNext>(
Task<Paging<T, TNext>> firstPageTask,
Func<TNext, Paging<T, TNext>> mapper,
Task<IPaginatable<T, TNext>> firstPageTask,
Func<TNext, IPaginatable<T, TNext>> mapper,
IPaginator? paginator = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{

View File

@ -0,0 +1,21 @@
using System.Collections.Generic;
namespace SpotifyAPI.Web
{
public interface IPaginatable<T>
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716")]
string Next { get; set; }
List<T> Items { get; set; }
}
public interface IPaginatable<T, TNext>
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716")]
string Next { get; set; }
List<T> Items { get; set; }
}
}

View File

@ -2,7 +2,17 @@ using System.Collections.Generic;
namespace SpotifyAPI.Web
{
public class CursorPaging<T>
public class CursorPaging<T> : IPaginatable<T>
{
public string Href { get; set; } = default!;
public List<T> Items { get; set; } = default!;
public int Limit { get; set; }
public string Next { get; set; } = default!;
public Cursor Cursors { get; set; } = default!;
public int Total { get; set; }
}
public class CursorPaging<T, TNext> : IPaginatable<T, TNext>
{
public string Href { get; set; } = default!;
public List<T> Items { get; set; } = default!;

View File

@ -2,7 +2,7 @@ namespace SpotifyAPI.Web
{
public class FollowedArtistsResponse
{
public CursorPaging<FullArtist> Artists { get; set; } = default!;
public CursorPaging<FullArtist, FollowedArtistsResponse> Artists { get; set; } = default!;
}
}

View File

@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace SpotifyAPI.Web
{
public class Paging<T>
public class Paging<T> : IPaginatable<T>
{
public string Href { get; set; } = default!;
public List<T> Items { get; set; } = default!;
@ -13,7 +13,7 @@ namespace SpotifyAPI.Web
public int Total { get; set; }
}
public class Paging<T, TNext>
public class Paging<T, TNext> : IPaginatable<T, TNext>
{
public string Href { get; set; } = default!;
public List<T> Items { get; set; } = default!;