我正在写一些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循环。它比简单地循环日历日期要复杂一些,因为它更像是包含特定节点的文件夹结构。有人能够建议一种简化这一点的方法吗?
答案 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
,则可以避免创建扩展方法。否则,如果您仍想使用上述扩展方法,则需要将其重命名为其他内容。