Reinventing the Paged IEnumerable, Weigert Style!

I am pretty sure someone else has done this, I've seen variations as PagedList<T>, but this is my style of a paged IEnumerable collection. I just store a reference to the collection and generate the paged data when the enumerator is needed, so you could technically add to a list that I'm referencing and the properties and results would be adjusted accordingly.

I don't mind reinventing the wheel when I can add some of my own personal flare ...

// Extension method for easy use
public static PagedEnumerable AsPaged(this IEnumerable collection, int currentPage = 1, int pageSize = 0)
{
    Contract.Requires(collection != null);
    Contract.Assume(currentPage >= 1);
    Contract.Assume(pageSize >= 0);

    return new PagedEnumerable(collection, currentPage, pageSize);
}

public class PagedEnumerable : IEnumerable
{
    public PagedEnumerable(IEnumerable collection, int currentPage = 1, int pageSize = 0)
    {
        Contract.Requires(collection != null);
        Contract.Assume(currentPage >= 1);
        Contract.Assume(pageSize >= 0);

        this.collection = collection;
        this.PageSize = pageSize;
        this.CurrentPage = currentPage;
    }

    IEnumerable collection;

    int currentPage;
    public int CurrentPage
    {
        get 
        {
            if (this.currentPage > this.TotalPages)
            {
                return this.TotalPages;
            }

            return this.currentPage; 
        }
        set
        {
            if (value < 1)
            {
                this.currentPage = 1;
            }
            else if (value > this.TotalPages)
            {
                this.currentPage = this.TotalPages;
            }
            else
            {
                this.currentPage = value;
            }
        }
    }

    int pageSize;
    public int PageSize
    {
        get 
        {
            if (this.pageSize == 0)
            {
                return this.collection.Count();
            }

            return this.pageSize;
        }
        set
        {
            this.pageSize = (value < 0) ? 0 : value;
        }
    }

    public int TotalPages
    {
        get
        {
            return (int)Math.Ceiling(this.collection.Count() / (double)this.PageSize);
        }
    }

    public IEnumerator GetEnumerator()
    {
        var pageSize = this.PageSize;
        var currentPage = this.CurrentPage;
        var startCount = (currentPage - 1) * pageSize;
            
        return this.collection.Skip(startCount).Take(pageSize).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

No Comments