如何使用LINQ来选择一个组合对象的所有后代 [英] How to use LINQ to select all descendants of a composite object
问题描述
如何才能让 ComponentTraversal.GetDescendants()
更好地使用LINQ?
问题
公共静态类ComponentTraversal
{
公共静态的IEnumerable<成分> GetDescendants(该复合复合)
{
//我能如何使用LINQ这更好的?
IList的<成分>后人=新的组件[] {};
的foreach(VAR孩子在composite.Children)
{
descendants.Add(子);
如果(孩子综合)
{
descendants.AddRange((子复合).GetDescendants());
}
}
返回的后裔;
}
}
公共类组件
{
公共字符串名称{;组; }
}
公共类复合:组件
{
公开的IEnumerable<成分>儿童{获得;组; }
}
公共类叶:组件
{
公共对象值{获得;组; }
}
答案
我编辑克里斯的回答来提供,我已经加入到我的公共库的通用扩展方法。我可以看到这是其他人也因此在这里有帮助的是:
公共静态的IEnumerable< T> GetDescendants< T>(这件T组件,Func键< T,布尔> isComposite,Func键< T,IEnumerable的< T>> getCompositeChildren)
{
VAR孩子= getCompositeChildren(组件);
返回儿童
。凡(isComposite)
.SelectMany(X => x.GetDescendants(isComposite,getCompositeChildren))
.Concat(儿童);
}
感谢克里斯!
另外,
请看看LukeH的回答在<一个href="http://blogs.msdn.com/b/wesdyer/archive/2007/03/23/all-about-iterators.aspx">http://blogs.msdn.com/b/wesdyer/archive/2007/03/23/all-about-iterators.aspx 。他的回答提供了一个更好的方式来处理,一般这个问题,但我没有选择它,因为它不是直接回答我的问题。
VAR的结果= composite.Children.OfType&lt;复合&GT;()的SelectMany(子=&GT;。child.GetDescendants( ))CONCAT(composite.Children)。
返回result.ToList();
在做从imperitive语法LINQ翻译,它通常是pretty的易取的翻译一步一个脚印的时间。下面是如何工作的:
- 这是遍历composite.Children,所以这将是集合我们应用的LINQ to。
- 一般有两种操作存在的在循环,所以让我们做他们的一次
- 在如果语句进行过滤。通常情况下,我们将使用位置,以执行一个过滤器,但在这种情况下,滤波器是基于类型。 LINQ有OfType建在此。
- 对于每一个孩子的复合,我们要递归调用GetDescendants并将结果添加到一个列表。每当我们想改造一个元素成别的东西,我们采用两种选择或的SelectMany。既然我们要转换的每个元素到一个列表,并把它们合并在一起,我们使用的SelectMany。
- 最后,在composite.Children自己添加,我们串连这些结果到最后。
How can I make ComponentTraversal.GetDescendants()
better using LINQ?
Question
public static class ComponentTraversal
{
public static IEnumerable<Component> GetDescendants(this Composite composite)
{
//How can I do this better using LINQ?
IList<Component> descendants = new Component[]{};
foreach(var child in composite.Children)
{
descendants.Add(child);
if(child is Composite)
{
descendants.AddRange((child as Composite).GetDescendants());
}
}
return descendants;
}
}
public class Component
{
public string Name { get; set; }
}
public class Composite: Component
{
public IEnumerable<Component> Children { get; set; }
}
public class Leaf: Component
{
public object Value { get; set; }
}
Answer
I edited Chris's answer to provide a generic extension method that I've added to my Common library. I can see this being helpful for other people as well so here it is:
public static IEnumerable<T> GetDescendants<T>(this T component, Func<T,bool> isComposite, Func<T,IEnumerable<T>> getCompositeChildren)
{
var children = getCompositeChildren(component);
return children
.Where(isComposite)
.SelectMany(x => x.GetDescendants(isComposite, getCompositeChildren))
.Concat(children);
}
Thanks Chris!
Also,
Please look at LukeH's answer at http://blogs.msdn.com/b/wesdyer/archive/2007/03/23/all-about-iterators.aspx . His answer provides a better way to approach this problem in general, but I did not select it because it was not a direct answer to my question.
var result = composite.Children.OfType<Composite>().SelectMany(child => child.GetDescendants()).Concat(composite.Children);
return result.ToList();
When doing a translation from imperitive syntax to LINQ, it is usually pretty easy to take the translation one step at a time. Here is how this works:
- This is looping over composite.Children, so that will be the collection we apply LINQ to.
- There are two general operations occuring in the loop, so lets do one of them at a time
- The "if" statement is performing a filter. Normally, we would use "Where" to perform a filter, but in this case the filter is based on type. LINQ has "OfType" built in for this.
- For each child composite, we want to recursively call GetDescendants and add the results to a single list. Whenever we want to transform an element into something else, we use either Select or SelectMany. Since we want to transform each element into a list and merge them all together, we use SelectMany.
- Finally, to add in the composite.Children themselves, we concatenate those results to the end.
这篇关于如何使用LINQ来选择一个组合对象的所有后代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!