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!