Создание лямбда-выражения WHERE для передачи в метод - PullRequest
0 голосов
/ 13 августа 2011

Мне нужно передать лямбда-выражение "где", которое будет использоваться в запросе LINQ внутри метода. Проблема в том, что я не знаю, с чем будет сравниваться значение where, пока не попаду в метод.

Теперь, чтобы объяснить далее и прояснить кое-что из того, что я сказал выше, я приведу немного надуманного примера.

Представьте, что у меня есть List<Products>, и мне нужно сузить этот список до одной записи, используя свойство productId объекта Products. Обычно я бы сделал это:

var product = productList.Where(p=>p.productId == 123).FirstOrDefault();

Теперь сделайте еще один шаг - мне нужно поместить вышеупомянутую логику в метод, который не ограничен List<Products>, а вместо этого List<T>, так что в идеале я бы назвал его так (и Я знаю, что нижеприведенное не сработает, это просто здесь, чтобы показать, чего я пытаюсь достичь):

myMethod(productList, p => p.productId == X)

С учетом того, что X неизвестен, пока я не внутри метода.

Наконец, для чего бы это ни стоило, я должен указать, что мой сбор данных - это OData DataServiceQuery.

Итак, чтобы подвести итог моего вопроса: мне нужно знать, как создать лямбда-выражение «где», которое я могу передать в метод, и как использовать его для набора объектов в запросе LINQ.

Ответы [ 3 ]

2 голосов
/ 13 августа 2011

С одной стороны, если вы собираетесь запросить IEnumerable<T>, вам необходимо убедиться, что ваше сравнение будет работать в первую очередь. В этом случае вы можете заставить свои объекты реализовывать интерфейс, который гарантирует, что они будут поддерживать сравнение.

Как только вы это сделаете, ваш метод может иметь общее ограничение, ограничивающее входные данные этими интерфейсами. В этот момент ваш метод может получить Func, который может быть передан предложению LINQ Where:

public interface Identifier
{
   int Id { get; set; }
}

public class Product : Identifier
{
   public int Id { get; set; }
   //Other stuff
}

public T GetMatch<T>(IEnumerable<T> collection, Func<T, int, bool> predicate) where T : Identifier
{
   int comparison = 5;
   return collection.Where(item => predicate(item, comparison)).FirstOrDefault();
}

Который может быть вызван как:

var match = GetMatch<Identifier>(collection, (x, y) => x.Id == y);

UPDATE: Я изменил приведенный выше код, чтобы принять параметр сравнения

2 голосов
/ 13 августа 2011

myMethod (productList, p => p.productId == X) - вы можете эмулировать этот трюк

    static void myMethod<T>(List<T> list, Func<T,bool> predicate, ref int x)
    {
        x = 5;
        var v = list.Where(predicate);
        foreach (var i in v)
            Console.Write(i);
        Console.ReadLine();
    }

    static void Main(string[] args)
    {
        List<int> x = new List<int> { 1, 2, 3, 4, 5 };
        int z = 0;
        myMethod(x, p => p == z, ref z);
    }

, но не уверены, решит ли он вашу проблему в целом

0 голосов
/ 13 августа 2011

Вы можете попробовать использовать класс PredicateBuilder из бесплатной библиотеки LinqKit ( учебник ).

Затем вы можете построить предикат, используя

PredicateBuilder predicate = PredicateBuilder.True<T>();
predicate = PredicateBuilder.And(predicate, p=> p.product_id == X);

, где X относится к типу T.

Вы можете использовать этот предикат в предложении where, например .Where(predicate), и возвращать IQueryable или возвращать сам предикат типа Expression<Func<T, bool>>

.
...