I suggest 2 ways of achieving this. You can opt with an utility method to get all the items or you can implement the Visitor Pattern, though it implies changing the RMenuItem
class.
Utility method:
static IEnumerable<RMenuItem> GetAllMenuItems(IList<RMenuItem> items)
{
if (items == null)
throw new ArgumentNullException("items");
Queue<RMenuItem> queue = new Queue<RMenuItem>(items);
while (queue.Count > 0)
{
var item = queue.Dequeue();
if (item.ChildrenItems != null)
{
foreach (var child in item.ChildrenItems)
{
queue.Enqueue(child);
}
}
yield return item;
}
}
I prefer an imperative way to a recursive because we can use iterator blocks.
Visitor Pattern:
public interface IRMenuItemVisitor
{
void Visit(RMenuItem item);
}
public class PrintRMenuItemVisitor : IRMenuItemVisitor
{
public void Visit(RMenuItem item)
{
Console.WriteLine(item);
}
}
public interface IRMenuItem
{
void Accept(IRMenuItemVisitor visitor);
}
public class RMenuItem : IRMenuItem
{
// ...
public void Accept(IRMenuItemVisitor visitor)
{
visitor.Visit(this);
if (ChildrenItems != null)
{
foreach (var item in ChildrenItems)
{
item.Accept(visitor);
}
}
}
}
Usage:
RMenuItem m1 = new RMenuItem
{
Name = "M1",
ChildrenItems = new List<RMenuItem> {
new RMenuItem { Name = "M11" },
new RMenuItem {
Name = "M12",
ChildrenItems = new List<RMenuItem> {
new RMenuItem { Name = "M121" },
new RMenuItem { Name = "M122" }
}
}
}
};
RMenuItem m2 = new RMenuItem
{
Name = "M2",
ChildrenItems = new List<RMenuItem> {
new RMenuItem { Name = "M21" },
new RMenuItem { Name = "M22" },
new RMenuItem { Name = "M23" }
}
};
IList<RMenuItem> menus = new List<RMenuItem> { m1, m2 };
foreach (var menu in GetAllMenuItems(menus))
{
Console.WriteLine(menu);
}
// or
IList<RMenuItem> menus = new List<RMenuItem> { m1, m2 };
foreach (var menu in menus)
{
menu.Accept(new PrintRMenuItemVisitor());
}