遍历 Linq fluent API 方法(C#)[关闭]

Posted

技术标签:

【中文标题】遍历 Linq fluent API 方法(C#)[关闭]【英文标题】:Iterate through Linq fluent API methods (C#) [closed] 【发布时间】:2021-06-07 09:38:25 【问题描述】:

我正在寻找一种方法来遍历先前构建的 Linq 方法集合,然后对其进行操作,例如更改表达式树。

这是一个例子:

我只想做一个 forEach(或类似的东西)来获得一个循环,其中:

我将 linq .Where(e => e.Summary == "sum") 放在第一位

我得到第二个位置的 linq .Where(l => l.Description == "asd")

我在最后一次迭代中得到了 linq .Take(2)

这可能吗?很可能需要反思,但我可以做到或找到它。

其他示例

使用上面的示例,我想查看 Ienumerable/Iqueryable 并获取第一个 where,得到 equivalent 结果:

var c = list
        .Where(e => e.Summary == "sum");

让我强调一下,我希望通过运行时使用 Ienumerable/Iqueryable 作为输入。

谢谢,

【问题讨论】:

这可能是您的方向:docs.microsoft.com/en-us/dotnet/api/… 吗?另见:docs.microsoft.com/en-us/dotnet/csharp/programming-guide/… 你想循环做什么?什么叫循环?与 linq 链接或反射有什么联系? 抱歉,您的问题已经很清楚了。请提供您实际尝试完成的示例。 注意:“表达式树应该是不可变的。这意味着如果要修改表达式树,则必须通过复制现有的表达式树并替换其中的节点来构造新的表达式树。 " - Immutability of Expression Trees 我添加了一个可能更容易掌握的示例 【参考方案1】:

我认为最简单的方法是创建只调用 WhereTake 函数的新函数(例如 _Where()_Take()),但还要保存您调用它们的事实有哪些论据。稍后您可以再次阅读它们。

这样做的缺点是您需要以某种方式存储哪些调用属于哪个调用。 IE。如果您有两个语句 list.Where().Where()list.Where().Take() 您需要保存哪些调用属于第一行,哪些属于第二行。

您还可以尝试使这些经过特殊处理的函数返回一个包含结果和调用信息的元组。然后你应该为每个 linq 方法创建两个函数:一个只接受一个可枚举的,另一个接受一个可枚举的元组和之前的调用信息。这样,您可以将新呼叫信息添加到旧呼叫信息中。如果使用扩展函数,当然要扩展可枚举和元组。

编辑

让我添加一个我的想法的例子......请注意,很难完美地序列化Where函数中给出的函数。有可能,例如检查Convert Func delegate to a string

Overloads.cs:

public static class Overloads

    public static (IEnumerable<T>, List<string>) Where_<T>(this IEnumerable<T> inp, Func<T, bool> predicate)
    
        return (inp.Where(predicate), new List<string>  ".Where(...)" );
    

    public static (IEnumerable<T>, List<string>) Where_<T>(this (IEnumerable<T>, List<string>) inp, Func<T, bool> predicate)
    
        inp.Item2.Add(".Where(...)");
        return (inp.Item1.Where(predicate), inp.Item2);
    

    public static (IEnumerable<T>, List<string>) Take_<T>(this IEnumerable<T> inp, int count)
    
        return (inp.Take(count), new List<string>  $".Take(count)" );
    

    public static (IEnumerable<T>, List<string>) Take_<T>(this (IEnumerable<T>, List<string>) inp, int count)
    
        inp.Item2.Add($".Take(count)");
        return (inp.Item1.Take(count), inp.Item2);
    

示例运行:

public static void Main(string[] args)

    var a = new List<int>  0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ;

    var (result, calls) = a
        .Where_(x => x % 2 == 0)
        .Where_(x => x % 3 == 0)
        .Take_(1);

    Console.WriteLine(string.Join(", ", result));
    Console.WriteLine(string.Join(", ", calls));

输出:

0
.Where(...), .Where(...), .Take(1)

【讨论】:

好答案。我认为对我来说最好的两个世界实际上是对此扩展方法进行新的覆盖实现,以存储此行为。你怎么看? 我认为您应该采用元组的方法来保持清洁,请检查我的答案... HTH

以上是关于遍历 Linq fluent API 方法(C#)[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

EF6:创建存储过程。使用 Fluent API 或 DBMigrations?

是否有使用 Fluent API 的 C# EF6 DbContext 生成器?

C#中的LINQ

通过 ASP.NET MVC 在 C# 视图中遍历匿名对象的嵌套 LINQ 查询

C#规范整理·集合和Linq

c#在遍历列表时删除元素-向后迭代或使用i--或使用linq同时迭代和删除?