【发布时间】:2009-04-08 23:30:59
【问题描述】:
我正在为分层数据源编写 LINQ 提供程序。我发现通过编写示例来展示我想要如何使用它,然后编写代码来支持这些用例,来设计我的 API 是最容易的。
我遇到的一个问题是在 LINQ 语句中表达“深度查询”或递归的简单/可重用/优雅的方式。换句话说,最好的区分方法是:
from item in immediate-descendants-of-current-node where ... select item
对比:
from item in all-descendants-of-current-node where ... select item
(编辑:请注意,以上这些示例都不一定反映我想要的查询结构。我对任何表达递归/深度的好方法感兴趣)
请注意我不是在问如何实现这样的提供程序,或者如何以允许递归的方式编写我的 IQueryable 或 IEnumerable。我是从编写 LINQ 查询并利用我的提供程序的人的角度来问的——他们表达是否要递归的直观方式是什么?
数据结构类似于典型的文件系统:文件夹可以包含子文件夹的集合,文件夹也可以包含项目的集合。所以 myFolder.Folders 代表了 myFolder 的所有直接子文件夹,而 myFolder.Items 包含了 myFolder 中的所有项目。这是一个站点层次结构的基本示例,很像带有文件夹和页面的文件系统:
(F)Products
(F)Light Trucks
(F)Z150
(I)Pictures
(I)Specs
(I)Reviews
(F)Z250
(I)Pictures
(I)Specs
(I)Reviews
(F)Z350
(I)Pictures
(I)Specs
(I)Reviews
(I)Splash Page
(F)Heavy Trucks
(F)Consumer Vehicles
(I)Overview
如果我写:
from item in lightTrucks.Items where item.Title == "Pictures" select item
表达查询获取轻型卡车下的所有项目或仅直接项目的意图的最直观方式是什么?区分这两种意图的侵入性最小、摩擦最小的方法?
我的第一个目标是能够将此 LINQ 提供程序转交给对 LINQ 有一定了解的其他开发人员,并允许他们编写递归和列表查询,而无需向他们提供编写递归 lambda 的教程。给定一个看起来不错的用法,我可以针对它编写提供程序。
补充说明:(我真的很讨厌交流这个!) - 这个 LINQ 提供程序是针对外部系统的,它不是简单地遍历对象图,在这种特定情况下也不是递归表达式实际上可以转化为任何类型的真正递归活动。只需要一种方法来区分“深”查询和“浅”查询。
那么,你认为最好的表达方式是什么?或者有没有我错过的标准表达方式?
【问题讨论】:
-
Rex 如果不了解您所期望的操作类型或您所公开的分层数据结构的更多信息,则很难回答您给出的两个示例的上下文之外的问题。你能告诉我们更多吗?
-
@Wolfbyte 添加了有关数据源的说明
-
请问:xml“后代”方法的不情愿是什么?由于这是基于迭代器块的,因此它不像缓冲所有内容。我还添加了一个“SelectDeep”(以反映标准的“SelectMany”),您可能会觉得它很有用。也许吧。
-
@Marc 对我来说,拥有一个代表小范围项目(当前子项)的对象但在该对象上拥有一个返回更大范围(所有后代)的方法是违反直觉的)。从消费者的角度来看,我希望类集合对象上的方法作用于原始对象的范围。
-
我见过的最好的例子是:Recursive LINQ with Y-Combinator。
标签: c# .net linq recursion hierarchical-data