walter
walter

Reputation: 547

is it possible to create anonymous type generics?

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

Answers (8)

Bala R
Bala R

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

Femaref
Femaref

Reputation: 61497

Yes, this is possible. I would do it the following way:

  1. Hide the implementation, only expose an interface:

    public interface IPagination<T>
    {
        int PageSize { get; set; }
        int TotalPages { get; }
        IQueryable<T> GetPage(int page);
    }
    
  2. 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);
            }
    }
    
  3. 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

Muad&#39;Dib
Muad&#39;Dib

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

Justin Morgan
Justin Morgan

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

Harry Steinhilber
Harry Steinhilber

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

Aliostad
Aliostad

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

JaredPar
JaredPar

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

Gats
Gats

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

Related Questions