检查树结构中的每个节点,Umbraco(提高效率)

时间:2012-07-09 08:54:04

标签: c# algorithm foreach umbraco

我正在写一些C#(。NET)与Umbraco 4.7一起将文章导入博客。简而言之,该算法旨在循环遍历每篇现有文章,并检查它是否与我们试图从XML中引入的新文章具有相同的ID。算法运行正常,但我不禁想到有四个foreach循环对于我正在做的事情是非常低效的。

foreach (Document yearNode in node.Children) //News > Years
{
    foreach (Document monthNode in yearNode.Children) //Years > Months
    {
        foreach (Document dayNode in monthNode.Children) //Months > Days
        {
            foreach (Document newsItem in dayNode.Children) //Days > Articles
            {
                // If there isn't an ID match, go ahead and create a new article node.         
            }

这是没有它的主要功能的基本算法,只是foreach循环。它比简单地循环日历日期要复杂一些,因为它更像是包含特定节点的文件夹结构。有人能够建议一种简化这一点的方法吗?

1 个答案:

答案 0 :(得分:4)

使用DocumentType获取所有文章节点的想法,您可以使用等效的this GetDescendants extension method来迭代特定文档类型的节点。

该方法专门针对NodeFactory的Node类编写,但可以轻松地为Document重写。要使用扩展方法,您需要创建一个新类并使其成为静态。例如:

using System;
using System.Collections.Generic;
using umbraco.cms.businesslogic.web;

namespace Example
{
    static class Extensions
    {
        public static IEnumerable<Document> GetDescendants(this Document document)
        {
            foreach (Document child in document.Children)
            {
                yield return child;

                foreach (Document grandChild in child.GetDescendants())
                {
                    yield return grandChild;
                }
            }
            yield break;
        }
    }
}

然后在我们的上下文中使用该方法:

var myDocuments = new Document(folderId)
    .GetDescendants()
    .Cast<Document>()
    .Where(d => d.ContentType.Alias == "myDocumentType");

if (myDocuments.Any(d => d.Id == myId))
{
    ...
}

注意:我不确定原因,但.OfType<Document>()之后似乎需要.Cast<Document>().GetDescendants()。 (请参阅下面的编辑

使用NodeFactory的Node而不是Document会更有效率,因为NodeFactory从XML缓存中提取信息,并且每次都不会像Document那样调用数据库。确实。使用NodeFactory的唯一缺点是它只包含那些已发布的节点,但通常你只想与它们一起使用。请参阅Difference between Node and Document

修改:在做了一些修补之后,我发现Document已经包含了GetDescendants()方法并返回IEnumerable这就是为什么我们有做.Cast<Document>()。因此,如果您仍然选择使用Document,则可以避免创建扩展方法。否则,如果您仍想使用上述扩展方法,则需要将其重命名为其他内容。