Ran into a situation today where I needed to get all of the base templates for a given item. Toyed with a few approaches including recursion. I figured there had to be a better way. So after quite a bit of Stack Overflow reading, and a few Sitecore blogs, I came up with this really simple solution:
public static IEnumerable<TemplateItem> GetAllMasters(this Item item)
{
var nodes = new Stack<TemplateItem>(new[] { item.Template });
while (nodes.Any())
{
var node = nodes.Pop();
yield return node;
foreach (var n in node.BaseTemplates) nodes.Push(n);
}
}
So instead of using recursion, which can in some extreme cases cause a Stack Overflow (unlikely in this circumstance but I like this solution better), the code uses some fancy C# footwork and effectively flattens the tree into one stack frame. The magic of yield return node; remembers where we loft off after each iteration (greatly simplified – see http://stackoverflow.com/questions/39476/what-is-the-yield-keyword-used-for-in-c for a better explanation) and continues on.
Note: I don’t recommend this approach for all such situations. It’s not a magic bullet for large trees. Unless your inheritance is massive though, this should be pretty low impact. I would definitely NOT use this to traverse content items! We’re just looking at base templates here!
UPDATE [06/01/2016]
@cassidydotdk brought to my attention the fact that there is an API solution for this that’s often overlooked:
var t = TemplateManager.GetTemplate(actionItem); t.GetBaseTemplates();
Reflection shows that this DOES give all base templates, not just the immediate ones. So ultimately using the TemplateManager is a better approach for this case, using yield return for code like this is still a powerful tool for simplifying and optimizing your code!
If you have any questions, you can always tweet it to me: @SitecoreJon or @JonUpchurch or leave a comment below!
