构建 lambda WHERE 表达式以传递到方法中

发布于 2024-11-29 08:56:18 字数 777 浏览 0 评论 0 原文

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

现在,为了进一步解释和澄清我上面所说的一些内容,我将提出一些人为的例子。

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

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

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

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

警告是 X直到我在该方法内部。

最后,就其价值而言,我需要指出我的数据集合是 OData DataServiceQuery

因此,重新总结我的问题:我需要知道如何构造可以传递到方法中的 lambda“where”表达式,以及如何针对 LINQ 查询中的对象集合使用它。

I need to pass in a "where" lambda expression that'll be used in a LINQ query inside a method. The problem is, I don't know what the where value will be compared against until I get into the method.

Now to explain further and clarify some of what I said above I'll come up with a bit of a contrived example.

Imagine I have a List<Products> and I need to narrow that list down to a single record using a productId property of the Products object. Normally I would do this:

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

Now take it a step further - I need to put the above logic into a method that isn't limited to a List<Products> but is instead a List<T> so ideally, I'd be calling it like this (and I know the below won't work, it's simply here to show what I am trying to achieve):

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

With the caveat being that X isn't known until I'm inside the method.

Finally, for what it's worth, I need to point out that my collection of data is an OData DataServiceQuery.

So, to re-summarize my question: I need to know how to construct a lambda "where" expression that I can pass into a method and how to use it against a collection of objects in a LINQ query.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

南街女流氓 2024-12-06 08:56:18

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);
    }

,但不确定它是否能完全解决您的问题

myMethod(productList, p => p.productId == X) - you can emulate with this trick

    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);
    }

but not sure if it solves your problem in whole

段念尘 2024-12-06 08:56:18

首先,如果您要查询 IEnumerable,您需要首先确保您的比较能够正常进行。在这种情况下,您可以使对象实现一个接口,以保证它们支持比较。

一旦你这样做了,你的方法就可以有一个通用约束来限制这些接口的输入。此时,您的方法可以采用 Func,该 Func 可以传递给 LINQWhere 子句:

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);

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

For one, if you are going to query an IEnumerable<T>, you will need to ensure that your comparison will work in the first place. In that case you can make your objects implement an interface that guarantees that they will support the comparison.

Once you do that, your method can have a generic constraint that limits the input to those interfaces. At that point, your method can take a Func, which can be passed to the LINQ Where clause:

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();
}

Which can be invoked like:

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

UPDATE:
I modified the above code to take in a comparison parameter

萤火眠眠 2024-12-06 08:56:18

您可以尝试使用免费 LinqKit 库中的 PredicateBuilder 类(教程< /a>)。

构造谓词

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

然后,您可以使用where X 的类型为 T

。您可以在 where 子句(例如 .Where(predicate))中使用此谓词,并返回 IQueryable 或返回谓词本身,该谓词为类型表达式>

You could try to use the PredicateBuilder class from the free LinqKit library(tutorial).

You can then construct a predicate using

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

where X is of type T.

You can use this predicate in a where clause such as .Where(predicate) and return an IQueryable or return the predicate itself which would be of type Expression<Func<T, bool>>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文