Поскольку в этом случае вы имеете дело с разными типами, вам придется реализовать общий интерфейс для каждого из них, чтобы сделать код универсальным. Основной подход заключается в создании интерфейса, который включает в себя любые необходимые свойства (например, DisplayText, ActionURL и т. Д.), А затем рекурсивно выполняет итерацию по коллекции.
Вот пример:
public interface IDataItem
{
string DisplayText { get; }
string ActionUrl { get; }
bool HasChildren { get; }
IEnumerable<IDataItem> GetChildren();
}
public void CreateTree(HtmlTextWriter writer, IEnumerable<IDataItem> collection)
{
writer.WriteFullBeginTag("ul");
foreach (var data in collection)
{
writer.WriteFullBeginTag("li");
writer.WriteBeginTag("a");
writer.WriteAttribute("href",data.ActionUrl);
writer.Write(HtmlTextWriter.TagRightChar);
writer.Write(data.DisplayText);
writer.WriteEndTag("a");
if(data.HasChildren)
CreateTree(writer, data.GetChildren());
writer.WriteEndTag("li");
}
writer.WriteEndTag("ul");
}
Вам нужно будет реализовать интерфейс для каждого из ваших типов, которые вы хотите включить в древовидную структуру. Простой переход в коллекцию типа верхнего уровня и метода, описанного выше, пройдет по иерархии, создавая необходимый вложенный список.