Created
March 6, 2021 22:52
-
-
Save CliffCrerar/1481df40c5d549651b16bce7abed3ebf to your computer and use it in GitHub Desktop.
C# Databook Paginator Service
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Dapper; | |
namespace TraqIt.Api.Services | |
{ | |
/// <summary> | |
/// Defines the contract of a databook page | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
public interface IDataPage<T> | |
{ | |
public int PageNumber { get; } | |
public IList<T> Page { get; } | |
} | |
/// <summary> | |
/// Concretion of the databook page contract | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
public class DataPage<T> : IDataPage<T> | |
{ | |
public int PageNumber { get; } | |
public IList<T> Page { get; } | |
/// <summary> | |
/// Constructor | |
/// </summary> | |
/// <param name="number">The databook page number</param> | |
/// <param name="page">The data page</param> | |
public DataPage(int number, IList<T> page) | |
{ | |
Page = page; | |
PageNumber = number; | |
} | |
/// <summary> | |
/// Inverts the new page dependancy | |
/// </summary> | |
/// <param name="number">The databook page number</param> | |
/// <param name="page">The databook page number</param> | |
/// <typeparam name="U">The Page Data Type</typeparam> | |
/// <returns></returns> | |
public static IDataPage<T> CreatePage(int number, List<T> page) | |
{ | |
return new DataPage<T>(number, page); | |
} | |
} | |
/// <summary> | |
/// Paging controller data contract | |
/// </summary> | |
public interface IPagingController | |
{ | |
public int RangeStart { get; } | |
public int PageCount { get; } | |
public int PageSize { get; } | |
public int CurrentPage { get; } | |
public bool IsFinalPage { get; } | |
public IEnumerable<int> RecordIndexRange { get; } | |
public void NextPage(); | |
} | |
/// <summary> | |
/// Defines the meta for the paging of data in the insert pages method. Defines the data partitioning strategy | |
/// for paging data | |
/// </summary> | |
public class PagingController : IPagingController | |
{ | |
public int RangeStart { get; private set; } | |
public int CurrentPage { get; private set; } | |
public bool IsFinalPage { get; private set; } | |
public int PageCount { get; } | |
public int PageSize { get; } | |
public IEnumerable<int> RecordIndexRange { get; private set; } | |
public PagingController(int rowCount, int pageSize) | |
{ | |
PageSize = pageSize; | |
PageCount = rowCount / PageSize; | |
CurrentPage = 0; | |
RangeStart = 0; | |
RecordIndexRange = Enumerable.Range(RangeStart, PageSize); | |
IsFinalPage = false; | |
} | |
/// <summary> | |
/// Method increments the paging controllers meta data | |
/// Like licking your finger to go to the next page of a magazine | |
/// </summary> | |
public void NextPage() | |
{ | |
CurrentPage += 1; | |
RangeStart += PageSize; | |
RecordIndexRange = Enumerable.Range(RangeStart, PageSize); | |
IsFinalPage = CurrentPage >= PageCount; | |
} | |
} | |
/// <summary> | |
/// Defines the data book contract | |
/// </summary> | |
/// <typeparam name="T">The page data type</typeparam> | |
public interface IDataBook<T> | |
{ | |
public Guid BookId { get; } | |
public string BookName { get; } | |
public IPagingController PagingController { get;} | |
public IList<IDataPage<T>> Pages { get; } | |
} | |
/// <summary> | |
/// Concretion of the data book contract | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
public class DataBook<T> : IDataBook<T> | |
{ | |
public Guid BookId { get; } | |
public string BookName { get; } | |
public IPagingController PagingController { get; private set; } | |
public IList<IDataPage<T>> Pages { get; } | |
private DataBook(string bookName) | |
{ | |
BookId = new Guid(); | |
Pages = new List<IDataPage<T>>(); | |
BookName = bookName; | |
} | |
/// <summary> | |
/// Runs a loop that partitions the data, assigns a page number to them and adds the page | |
/// to the data book. | |
/// </summary> | |
/// <param name="Data">The selected data from the database</param> | |
/// <param name="PageSize">The page size passed in via the API call</param> | |
/// <returns>Returns this object following page insertion</returns> | |
private IDataBook<T> InsertPages(IEnumerable<T> Data, int PageSize) | |
{ | |
PagingController = new PagingController(Data.Count(), PageSize); | |
while (!PagingController.IsFinalPage) | |
{ | |
var pageDataContent = Data.Where((row, idx) => PagingController.RecordIndexRange.Contains(idx)); | |
Pages.Add(DataPage<T>.CreatePage(PagingController.CurrentPage,pageDataContent.AsList())); | |
PagingController.NextPage(); | |
} | |
return this; | |
} | |
/// <summary> | |
/// Static method used to self instantiate as inversion of control mechanism | |
/// </summary> | |
/// <param name="Data">A set of records / array of objects / collection</param> | |
/// <param name="PageSize">The size the partition</param> | |
/// <param name="dataBookName">OPTIONAL: name of the databook</param> | |
/// <returns></returns> | |
public static IDataBook<T> CreateDataBook(IEnumerable<T> Data, int PageSize, string dataBookName = "anonymous") | |
{ | |
return new DataBook<T>(dataBookName).InsertPages(Data, PageSize); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment