Методы расширения, не работающие для интерфейса
-
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>