2012-02-13 3 views
3

Я работаю над методом расширения, чтобы обеспечить возможности фильтрации для нескольких объектов. Участвующие объекты имеют разные типы, но имеют общие поля, которые можно искать.Создание универсального метода расширения для обеспечения функциональности фильтрации

Ниже приведена работа, однако мне было интересно, можно ли это «обобщить», чтобы кастинг от общего к явному типу не обязательно возникал?

public static IQueryable<T> PriceLow<T>(this IQueryable<T> query, decimal? priceLow) 
{ 
    if (typeof(T) == typeof(Entity1)) 
    { 
     var innerQuery = (IQueryable<Entity1>) query; 
     var results = priceLow.HasValue ? innerQuery.Where(o => (o.ListPrice > priceLow.Value)) : innerQuery; 
     return (IQueryable<T>) results; 
    } 

    if (typeof(T) == typeof(Entity2)) 
    { 
     var innerQuery = (IQueryable<Entity2>)query; 
     var results = priceLow.HasValue ? innerQuery.Where(o => (o.ListPrice > priceLow.Value)) : innerQuery; 
     return (IQueryable<T>)results; 
    } 

    return null; 
} 

Пример использования:

var foo = _repository.GetAllEntity1().PriceLow(_searchCritera.PriceLow); 

ответ

3

Если вы можете изменить два типа сущностей для реализации общего интерфейса, который имеет общие свойства/методы, то вы можете использовать ограничение общего типа. Это также будет работать с общим базовым классом.

ли это, и тогда ваша подпись выглядит следующим образом (захламление детали опущены):

public static IQueryable<T> PriceLow<T>(...) 
    where T : ICommonInterface 
+0

Спасибо, Пол, имел пробел в знаниях о том, как указать общий базовый класс для метода (где T: ICommonInterface) – Jesse

2

Как насчет сделать ваши объекты наследуют от базового типа, который содержит доступные для поиска поля. Таким образом, ваш метод фильтрации должен знать только об одном базовом типе.

+0

Если вы исключите родословную, просто сделав ее работу с базовым типом, вы существенно предотвратите дальнейшую цепочку. Так как он вернет «IQueryable» базового типа, для привязки вызова к одному из подтипов потребуется приведение. –

1

Один подход заключается в определении интерфейса и добавить, что интерфейс, как одна из вещей, ваш класс наследует от. Интерфейс не должен содержать ничего вообще. Его можно просто использовать в качестве маркера.

Затем, чтобы ваш метод расширения требовал, чтобы аргументом был этот интерфейс.

+1

Интерфейс маркера не будет работать, поскольку на самом деле код использует свойство, которое находится не только на объекте ' –

+0

А, это ты. Похоже, вам нужно добавить некоторую общую реализацию в этот интерфейс. –