This problem is not well suited to LINQ, although you could write an extension method to perform the search and return an IEnumerable<MyClass>
that represents the route back to root. Given the possibility of infinite loops and routes that do not complete, it's probably a good idea to track progress through the graph ensuring that a specific Id
is not visited more than once.
public static class MyClassEx
{
public static IEnumerable<MyClass> FindSourcePath(
this MyClass startItem,
IList<MyClass> items)
{
return startItem.FindSourcePath(items.ToDictionary(x => x.Id));
}
public static IEnumerable<MyClass> FindSourcePath(
this MyClass startItem,
IDictionary<int, MyClass> itemDic)
{
var curr = startItem;
var visited = new HashSet<int>();
while (visited.Add(curr.Id))
{
yield return curr;
if (curr.ParentId == 0)
{
yield break;
}
if (!itemDic.TryGetValue(curr.ParentId, out curr))
{
throw new Exception("invalid parent ref");
}
}
throw new Exception("loop detected");
}
}
And use it:
List<MyClass> allItems = //...
var someItem = allItems[7];
IEnumerable<MyClass> hopsToRoot = someItem.FindSourcePath(allItems);
to yield (in your example) the sequence
-------------
| MyClass |
-------------
Id | ParentId
=============
8 | 6
6 | 2
2 | 7
7 | 1
1 | 0