Методы расширения не работают для интерфейса - PullRequest
6 голосов
/ 17 сентября 2008

Вдохновленный витриной MVC, последний проект, над которым я работаю, использует методы расширения в IQueryable для фильтрации результатов.

У меня есть этот интерфейс;

IPrimaryKey
{
  int ID { get; }
}

и у меня есть этот метод расширения

public static IPrimaryKey GetByID(this IQueryable<IPrimaryKey> source, int id)
{
    return source(obj => obj.ID == id);
}

Допустим, у меня есть класс SimpleObj, который реализует IPrimaryKey. Когда у меня есть IQueryable из SimpleObj, метод GetByID не существует, если только я явно не приведу его как IQueryable из IPrimaryKey, что не идеально.

Я что-то здесь упускаю?

Ответы [ 3 ]

13 голосов
/ 17 сентября 2008

Работает, когда все сделано правильно. Решение cfeduke работает. Однако вам не нужно делать интерфейс IPrimaryKey универсальным, на самом деле вам вообще не нужно менять свое первоначальное определение:

public static IPrimaryKey GetByID<T>(this IQueryable<T> source, int id) where T : IPrimaryKey
{
    return source(obj => obj.ID == id);
}
4 голосов
/ 17 сентября 2008

Редактировать: Решение Конрада лучше, потому что оно намного проще. Приведенное ниже решение работает, но требуется только в ситуациях, подобных ObjectDataSource, где метод класса извлекается с помощью отражения без перехода по иерархии наследования. Очевидно, здесь этого не происходит.

Это возможно, мне приходилось реализовывать подобный шаблон, когда я проектировал специальное решение для инфраструктуры объектов для работы с ObjectDataSource:

public interface IPrimaryKey<T> where T : IPrimaryKey<T>
{
    int Id { get; }
}

public static class IPrimaryKeyTExtension
{
     public static IPrimaryKey<T> GetById<T>(this IQueryable<T> source, int id) where T : IPrimaryKey<T>
     {
         return source.Where(pk => pk.Id == id).SingleOrDefault();
     }
}

public class Person : IPrimaryKey<Person>
{
    public int Id { get; set; }
}

Фрагмент использования:

var people = new List<Person>
{
    new Person { Id = 1 },
    new Person { Id = 2 },
    new Person { Id = 3 }
};

var personOne = people.AsQueryable().GetById(1);
2 голосов
/ 17 сентября 2008

Это не может работать из-за того, что у дженериков нет возможности следовать шаблонам наследования. то есть. IQueryable отсутствует в дереве наследования IQueryable

...