0

我正在编写一些 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 循环。它比简单地循环浏览日历日期要复杂一些,因为它更多的是包含特定节点的文件夹结构。任何人都可以提出一种简化这一点的方法吗?

4

1 回答 1

4

使用通过 获取所有文章节点的想法,您可以使用与此 GetDescendants 扩展方法DocumentType等效的方法来遍历特定文档类型的节点。

该方法是专门为 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>()or.Cast<Document>()之后是必需的.GetDescendants()。(见下面的编辑

使用 NodeFactory 会更有效,Node因为DocumentNodeFactory 从 XML 缓存中提取它的信息,并且不会每次都调用数据库Document。使用 NodeFactory 的唯一缺点是它只包含那些已发布的节点,但通常您无论如何都只想使用这些节点。请参阅节点和文档之间的区别

编辑:在做了一些修改之后,我发现它Document已经包含一个GetDescendants()方法并且返回一个IEnumerable,这就是为什么我们必须做.Cast<Document>(). 因此,如果您选择仍然使用Document. 否则,如果您仍想使用上述扩展方法,则需要将其重命名为其他名称。

于 2012-07-09T15:26:39.297 回答