Reputation: 547
I've built a pagination class that works well for a specific data type, but now I need to make the type dynamic
here is my code
public class Pagination {
public IQueryable<Character> Items { get; set; }
public int PageSize { get; set; }
public int TotalPages {
get {
if (this.Items.Count() % this.PageSize == 0)
return this.Items.Count() / this.PageSize;
else
return (this.Items.Count() / this.PageSize) + 1;
}
}
public Pagination(IQueryable<Character> items, int pageSize) {
this.PageSize = pageSize;
this.Items = items;
}
public IQueryable<Character> GetPage(int pageNumber) {
pageNumber = pageNumber - 1;
return this.Items.Skip(this.PageSize * pageNumber).Take(this.PageSize);
}
}
as you can see, this pagination class works only for 'Character', is it possible to create anonymous data type and invoke generic methods such as Skip and Take?
Upvotes: 1
Views: 594
Reputation: 109037
This generic class should do the job.
public class Pagination<T>
{
public IQueryable<T> Items { get; set; }
public int PageSize { get; set; }
public int TotalPages
{
get
{
if (this.Items.Count() % this.PageSize == 0)
return this.Items.Count() / this.PageSize;
else
return (this.Items.Count() / this.PageSize) + 1;
}
}
public Pagination(IQueryable<T> items, int pageSize)
{
this.PageSize = pageSize;
this.Items = items;
}
public IQueryable<T> GetPage(int pageNumber)
{
pageNumber = pageNumber - 1;
return this.Items.Skip(this.PageSize * pageNumber).Take(this.PageSize);
}
}
Upvotes: 1
Reputation: 61497
Yes, this is possible. I would do it the following way:
Hide the implementation, only expose an interface:
public interface IPagination<T>
{
int PageSize { get; set; }
int TotalPages { get; }
IQueryable<T> GetPage(int page);
}
Make the Pagination
class generic and only an internal implementation (the outside only sees the interface)
public class Pagination<T> : IPagination<T> {
public IQueryable<T> Items { get; set; }
public int PageSize { get; set; }
public int TotalPages {
get {
if (this.Items.Count() % this.PageSize == 0)
return this.Items.Count() / this.PageSize;
else
return (this.Items.Count() / this.PageSize) + 1;
}
}
internal Pagination(IQueryable<T> items, int pageSize) {
this.PageSize = pageSize;
this.Items = items;
}
public IQueryable<T> GetPage(int pageNumber) {
pageNumber = pageNumber - 1;
return this.Items.Skip(this.PageSize * pageNumber).Take(this.PageSize);
}
}
Offer an extension method to convert:
public static IPagination<T> AsPagination (this IQueryable<T> source, int pageSize)
{
if(source == null)
throw new ArgumentNullException("source");
return new Pagination<T>(source, pageSize);
}
Upvotes: 1
Reputation: 29266
this should be pretty simple... try this...
public class Pagination<_type>
{
public IQueryable<_type> Items { get; set; }
public int PageSize { get; set; }
public int TotalPages {
get {
if (this.Items.Count() % this.PageSize == 0)
return this.Items.Count() / this.PageSize;
else
return (this.Items.Count() / this.PageSize) + 1;
}
}
public Pagination(IQueryable<_type> items, int pageSize) {
this.PageSize = pageSize;
this.Items = items;
}
public IQueryable<_type> GetPage(int pageNumber) {
pageNumber = pageNumber - 1;
return this.Items.Skip(this.PageSize * pageNumber).Take(this.PageSize);
}
}
you might want to add a constraint on _type, like this (makes it so _type MUST be a class):
public class Pagination< _type > where _type : class
Upvotes: 1
Reputation: 30700
Have you tried this?
public class Pagination<T> where T : class
{
public IQueryable<T> Items { get; set; }
public int PageSize { get; set; }
public int TotalPages {
get {
if (this.Items.Count() % this.PageSize == 0)
return this.Items.Count() / this.PageSize;
else
return (this.Items.Count() / this.PageSize) + 1;
}
}
public Pagination(IQueryable<T> items, int pageSize) {
this.PageSize = pageSize;
this.Items = items;
}
public IQueryable<T> GetPage(int pageNumber) {
pageNumber = pageNumber - 1;
return this.Items.Skip(this.PageSize * pageNumber).Take(this.PageSize);
}
}
Upvotes: 0
Reputation: 5239
Would this work for you?
public class Pagination<T> {
public IQueryable<T> Items { get; set; }
public int PageSize { get; set; }
public int TotalPages {
get {
if (this.Items.Count() % this.PageSize == 0)
return this.Items.Count() / this.PageSize;
else
return (this.Items.Count() / this.PageSize) + 1;
}
}
public Pagination(IQueryable<T> items, int pageSize) {
this.PageSize = pageSize;
this.Items = items;
}
public IQueryable<T> GetPage(int pageNumber) {
pageNumber = pageNumber - 1;
return this.Items.Skip(this.PageSize * pageNumber).Take(this.PageSize);
}
}
I'm not certain I see the correlation with anonymous types? Why do you need that to get this type to work for types other than Character
?
Upvotes: 0
Reputation: 81700
Yes, you can create the class as a generic class:
public class Pagination<T> {
public IQueryable<T> Items { get; set; }
public int PageSize { get; set; }
public int TotalPages {
get {
if (this.Items.Count() % this.PageSize == 0)
return this.Items.Count() / this.PageSize;
else
return (this.Items.Count() / this.PageSize) + 1;
}
}
public Pagination(IQueryable<T> items, int pageSize) {
this.PageSize = pageSize;
this.Items = items;
}
public IQueryable<T> GetPage(int pageNumber) {
pageNumber = pageNumber - 1;
return this.Items.Skip(this.PageSize * pageNumber).Take(this.PageSize);
}
}
Upvotes: 5
Reputation: 755457
Sure it's possible but it's typically only useful within a method body. For example
var array = new[] {
new { Name = "Jared", Age = 30 },
new { Name = "Bob", Age = 21 }
};
var query = array.Skip(1).Take(1);
This becomes problematic to pass between methods though because there is no way to state the name of an anonymous type hence nothing to put in for the T
in IEnumerable<T>
. It's possible to do with generic tricks but it doesn't appear to fit what you need for this scenario
Upvotes: 0
Reputation: 3462
You just use generics for a base class and inherit, implementing the class.
public class Pagination <T> where T : class
Then put T in all places you currently have the Character class
Upvotes: 3