用LINQ进行recursion控制search
如果我想在ASP.NET页面上查找checkbox,我可以使用下面的LINQ查询。
var checkBoxes = this.Controls .OfType<CheckBox>() .TakeWhile<CheckBox>(cb => cb.Checked);
如果checkbox嵌套在当前的控件集合中,那么工作正常,但我想知道如何通过深入到顶层控件的控件集合来扩展search。
问题在这里被问到:
查找在ASP.NET中使用特定接口的控件
并收到非LINQ的答案,我已经有了我自己的types和ID作为扩展方法的recursion控制search版本,但我只是想知道在LINQ中这是多么容易做?
把recursiontypes/ ID检查出来,所以只要有一个“给我所有的控制,recursion”的方法,例如
public static IEnumerable<Control> GetAllControls(this Control parent) { foreach (Control control in parent.Controls) { yield return control; foreach(Control descendant in control.GetAllControls()) { yield return descendant; } } }
这有点低效(就创build大量的迭代器而言),但我怀疑你会有一个非常深的树。
然后,您可以将原始查询写为:
var checkBoxes = this.GetAllControls() .OfType<CheckBox>() .TakeWhile<CheckBox>(cb => cb.Checked);
(编辑:更改AllControls GetAllControls并正确使用它作为一种方法。)
public static IEnumerable<Control> AllControls(this Control container) { //Get all controls var controls = container.Controls.Cast<Control>(); //Get all children var children = controls.Select(c => c.AllControls()); //combine controls and children var firstGen = controls.Concat(children.SelectMany(b => b)); return firstGen; }
现在基于上面的function,我们可以做这样的事情:
public static Control FindControl(this Control container, string Id) { var child = container.AllControls().FirstOrDefault(c => c.ID == Id); return child; }
我build议使AllControls
recursion是:
public static IEnumerable<Control> AllControls(this Control parent) { foreach (Control control in parent.Controls) { yield return control; } foreach (Control control in parent.Controls) { foreach (Control cc in AllControls(control)) yield return cc; } }
第二个foreach
看起来很奇怪,但这是我知道“扁平化”recursion调用的唯一方法。