diff --git a/src/Coscine.ApiClient/Coscine.ApiClient.csproj b/src/Coscine.ApiClient/Coscine.ApiClient.csproj index bf6b4184ae1eda43a930d7ea831d6e1f8679926b..370babd08eb588616865f955f6bfaa0f3e9d23a7 100644 --- a/src/Coscine.ApiClient/Coscine.ApiClient.csproj +++ b/src/Coscine.ApiClient/Coscine.ApiClient.csproj @@ -26,6 +26,7 @@ <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.2" /> + <PackageReference Include="System.Linq.Async" Version="6.0.1" /> <PackageReference Include="Winton.Extensions.Configuration.Consul" Version="3.3.0" /> </ItemGroup> diff --git a/src/Coscine.ApiClient/PaginationHelper.cs b/src/Coscine.ApiClient/PaginationHelper.cs index 2006d2f30950b43b1805c5b755b2526e0fa0a6f2..9aaf21ee6104f986f76d7b5ba8dc2bc878dc4d4c 100644 --- a/src/Coscine.ApiClient/PaginationHelper.cs +++ b/src/Coscine.ApiClient/PaginationHelper.cs @@ -1,6 +1,7 @@ using Coscine.ApiClient.Core.Model; using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace Coscine.ApiClient; @@ -10,6 +11,7 @@ namespace Coscine.ApiClient; /// </summary> public static class PaginationHelper { + // TODO: The naming is confusing, since this method is awaitable. This should be GetAllAsync /// <summary> /// Asynchronously retrieves all items of type <typeparamref name="T"/> across all pages. /// </summary> @@ -26,7 +28,7 @@ public static class PaginationHelper /// This function should encapsulate the logic to retrieve items for the specified page number. /// </param> /// <returns> - /// An asynchronous enumerable <see cref="IAsyncEnumerable{T}"/> that represents the sequence of items. + /// An enumerable <see cref="IEnumerable{T}"/> that represents the sequence of items. /// The sequence is lazily generated, yielding items as they are retrieved from each page. /// </returns> /// <example> @@ -34,13 +36,50 @@ public static class PaginationHelper /// Usage example: /// </para> /// <code> - /// var allItems = PaginationHelper.GetAllAsync<ProjectAdminDtoPagedResponse, ProjectAdminDto>(pageNumber => FetchItemsPageAsync(pageNumber)); + /// var allItems = PaginationHelper.GetAll<ProjectAdminDtoPagedResponse, ProjectAdminDto>(pageNumber => FetchItemsPageAsync(pageNumber)); /// </code> /// <para> /// This asynchronously retrieves all items across all pages using the provided function <c>FetchItemsPageAsync</c>, /// which is expected to return a paginated response object with "Data" and "Pagination" properties. /// </para> /// </example> + public static async Task<IEnumerable<T>> GetAll<S, T>(Func<int, Task<S>> pageRequest) where T : class + { + return await GetAllAsync<S, T>(pageRequest).ToListAsync(); + } + + // TODO: The naming is confusing, since this method is nothing which is awaitable. This should be something like GetAllAsyncList + /// <summary> + /// Retrieves all items of type <typeparamref name="T"/> across all pages with an asynchronous list. + /// </summary> + /// <remarks> + /// This method repeatedly calls the provided <paramref name="pageRequest"/> function to fetch items from multiple pages. + /// It lazily generates an asynchronous sequence of items, yielding each item as it becomes available. The method employs reflection + /// to dynamically interact with the response object of type <typeparamref name="S"/>, enabling a flexible approach to handle various types of paginated data. + /// Ensure that the <typeparamref name="S"/> type has "Data" and "Pagination" properties, with "Data" being an <see cref="IEnumerable{T}"/>. + /// </remarks> + /// <typeparam name="S">The type of the paginated response object. This object must have "Data" and "Pagination" properties.</typeparam> + /// <typeparam name="T">The type of the items in the paginated collection. This type must be a class.</typeparam> + /// <param name="pageRequest"> + /// A function that takes an integer (representing the page number) and returns a <see cref="Task{TResult}"/> where <c>TResult</c> is <typeparamref name="S"/>. + /// This function should encapsulate the logic to retrieve items for the specified page number. + /// </param> + /// <returns> + /// An asynchronous enumerable <see cref="IAsyncEnumerable{T}"/> that represents the sequence of items. + /// The sequence is lazily generated, yielding items as they are retrieved from each page. + /// </returns> + /// <example> + /// <para> + /// Usage example: + /// </para> + /// <code> + /// var allItems = PaginationHelper.GetAllAsync<ProjectAdminDtoPagedResponse, ProjectAdminDto>(pageNumber => FetchItemsPageAsync(pageNumber)); + /// </code> + /// <para> + /// This retrieves all items across all pages using the provided function <c>FetchItemsPageAsync</c>, + /// which is expected to return a paginated response object with "Data" and "Pagination" properties and provides them with a yield statement. + /// </para> + /// </example> public static async IAsyncEnumerable<T> GetAllAsync<S, T>(Func<int, Task<S>> pageRequest) where T : class { var currentPage = 1; @@ -72,4 +111,4 @@ public static class PaginationHelper currentPage++; } } -} \ No newline at end of file +}