Методы расширения, не работающие для интерфейса

StackOverflow https://stackoverflow.com/questions/82442

  •  01-07-2019
  •  | 
  •  

Вопрос

Вдохновленный MVC storefront, последний проект, над которым я работаю, использует методы расширения в 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, что далеко не идеально.

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

Это было полезно?

Решение

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

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

Другие советы

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

Это возможно, мне пришлось реализовать аналогичный шаблон, когда я разрабатывал пользовательское решение entity Framework для работы с 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);

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top