Можно ли создать дженерики анонимного типа? - PullRequest
1 голос
/ 08 апреля 2011

Я создал класс пагинации, который хорошо работает для определенного типа данных, но теперь мне нужно сделать тип динамическим

вот мой код

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);
    }
}

Как вы можете видеть, этот класс разбиения на страницы работает только для 'Character', возможно ли создать анонимный тип данных и вызвать универсальные методы, такие как Skip и Take?

Ответы [ 8 ]

5 голосов
/ 08 апреля 2011

Да, вы можете создать класс как универсальный класс:

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);
    }
}
3 голосов
/ 08 апреля 2011

Вы просто используете дженерики для базового класса и наследуете, реализуя класс.

public class Pagination <T> where T : class

Затем поместите T во все места, где у вас есть класс персонажей

1 голос
/ 08 апреля 2011

Да, это возможно. Я бы сделал это следующим образом:

  1. Скрыть реализацию, только выставить интерфейс:

    public interface IPagination<T>
    {
        int PageSize { get; set; }
        int TotalPages { get; }
        IQueryable<T> GetPage(int page);
    }
    
  2. Сделать класс Pagination универсальным и только внутренней реализацией (внешний вид видит только интерфейс)

    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. Предложите метод расширения для преобразования:

     public static IPagination<T> AsPagination (this IQueryable<T> source, int pageSize)
     {
         if(source == null)
             throw new ArgumentNullException("source");
         return new Pagination<T>(source, pageSize);
     }
    
1 голос
/ 08 апреля 2011

Этот общий класс должен выполнять эту работу.

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);
    }
}
1 голос
/ 08 апреля 2011

это должно быть довольно просто ... попробуй это ...

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);
    }
}

Возможно, вы захотите добавить ограничение на _type, например так (делает так, что _type ДОЛЖЕН быть классом):

public class Pagination< _type > where _type : class
0 голосов
/ 08 апреля 2011

Вы пробовали это?

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);
    }
}
0 голосов
/ 08 апреля 2011

Будет ли это работать для вас?

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);
    }
}

Я не уверен, что вижу связь с анонимными типами? Зачем вам это нужно, чтобы этот тип работал для типов, отличных от Character?

0 голосов
/ 08 апреля 2011

Конечно, это возможно, но обычно полезно только в теле метода. Например

var array = new[] {
  new { Name = "Jared", Age = 30 },
  new { Name = "Bob", Age = 21 }
};
var query = array.Skip(1).Take(1);

Это становится проблематичным для передачи между методами, потому что нет способа указать имя анонимного типа, поэтому нечего вставлять для T в IEnumerable<T>. Это можно сделать с помощью общих приемов, но они не соответствуют тому, что вам нужно для этого сценария

...