构建一个lambda WHERE表达式以传递给方法

时间:2011-08-12 21:12:19

标签: linq c#-4.0 lambda odata

我需要传入一个“where”lambda表达式,它将在方法内的LINQ查询中使用。问题是,在进入方法之前,我不知道将比较哪个值。

现在进一步解释并澄清我上面所说的一些内容,我会想出一些人为的例子。

想象一下,我有一个List<Products>,我需要使用Products对象的productId属性将该列表缩小到单个记录。通常我会这样做:

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

现在更进一步 - 我需要将上述逻辑放入一个不限于List<Products>的方法,而是List<T>,所以理想情况下,我会称之为像这样(我知道下面的内容不起作用,只是在这里展示我想要实现的目标):

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

需要注意的是,在我进入方法之前,X不知道。

最后,为了它的价值,我需要指出我的数据集合是一个OData DataServiceQuery

所以,重新总结一下我的问题:我需要知道如何构造一个lambda“where”表达式,我可以将其传递给一个方法,以及如何在LINQ查询中对象集合中使用它。

3 个答案:

答案 0 :(得分:2)

myMethod(productList,p =&gt; 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);
    }

但不确定它是否解决了整个问题

答案 1 :(得分:2)

首先,如果您要查询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);

<强>更新 我修改了上面的代码以接受比较参数

答案 2 :(得分:0)

您可以尝试使用免费的LinqKit库中的PredicateBuilder类(tutorial)。

然后,您可以使用

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

其中X是T型。

您可以在诸如.Where(predicate)之类的where子句中使用此谓词并返回IQueryable或返回类型为Expression<Func<T, bool>>的谓词本身