C# 检查树状结构中的每个节点,Umbraco(提高效率)
我正在编写一些C#(.NET)来与Umbraco 4.7合作,将文章导入博客。简而言之,此算法旨在循环浏览所有现有文章,并检查它是否与我们试图从XML中获取的新文章具有相同的ID。该算法工作正常,但我忍不住认为有四个foreach循环对于我正在做的事情来说是非常低效的C# 检查树状结构中的每个节点,Umbraco(提高效率),c#,algorithm,foreach,umbraco,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.Childr
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循环。它比简单地循环日历日期要复杂一些,因为它更像是包含特定节点的文件夹结构。有人能提出一种简化的方法吗 使用通过
DocumentType
获取所有文章节点的想法,您可以使用的等价物来迭代特定文档类型的节点
该方法是专门为NodeFactory的节点
类编写的,但可以轻松地为文档
重写。要使用扩展方法,您需要创建一个新类并使其成为静态的。例如:
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;
}
}
}
使用系统;
使用System.Collections.Generic;
使用umbraco.cms.businesslogic.web;
名称空间示例
{
静态类扩展
{
公共静态IEnumerable GetSubstands(此文档)
{
foreach(Document.Children中的文档子级)
{
退换子女;
foreach(在child.getsubstands()中记录孙子)
{
收益回报孙子;
}
}
屈服断裂;
}
}
}
然后在我们的上下文中使用该方法:
var myDocuments = new Document(folderId)
.GetDescendants()
.Cast<Document>()
.Where(d => d.ContentType.Alias == "myDocumentType");
if (myDocuments.Any(d => d.Id == myId))
{
...
}
var myDocuments=新文档(folderId)
.gets()
.Cast()
。其中(d=>d.ContentType.Alias==“myDocumentType”);
if(myDocuments.Any(d=>d.Id==myId))
{
...
}
注意:我不知道为什么,但似乎在.getsubjects()
之后需要.OfType()
或.Cast()
。(请参见下面的编辑)
使用NodeFactory的节点
比使用文档
更有效,因为NodeFactory从XML缓存中提取其信息,并且不像文档
那样每次调用数据库。使用NodeFactory的唯一缺点是它只包含那些已发布的节点,但通常您只希望使用这些节点。看
Edit:在做了一些修改之后,我发现
Document
已经包含了一个getsubstands()
方法,该方法返回一个IEnumerable
,这就是为什么我们必须执行.Cast()
。因此,如果您选择仍然使用文档
,似乎可以避免创建扩展方法。否则,如果您仍然希望使用类似于上述扩展方法的方法,则需要将其重命名为其他方法。使用通过DocumentType
获取所有文章节点的想法,您可以使用的等效方法来迭代特定文档类型的节点
该方法是专门为NodeFactory的节点
类编写的,但可以轻松地为文档
重写。要使用扩展方法,您需要创建一个新类并使其成为静态的。例如:
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;
}
}
}
使用系统;
使用System.Collections.Generic;
使用umbraco.cms.businesslogic.web;
名称空间示例
{
静态类扩展
{
公共静态IEnumerable GetSubstands(此文档)
{
foreach(Document.Children中的文档子级)
{
退换子女;
foreach(在child.getsubstands()中记录孙子)
{
收益回报孙子;
}
}
屈服断裂;
}
}
}
然后在我们的上下文中使用该方法:
var myDocuments = new Document(folderId)
.GetDescendants()
.Cast<Document>()
.Where(d => d.ContentType.Alias == "myDocumentType");
if (myDocuments.Any(d => d.Id == myId))
{
...
}
var myDocuments=新文档(folderId)
.gets()
.Cast()
。其中(d=>d.ContentType.Alias==“myDocumentType”);
if(myDocuments.Any(d=>d.Id==myId))
{
...
}
注意:我不知道为什么,但似乎在.getsubjects()
之后需要.OfType()
或.Cast()
。(请参见下面的编辑)
使用NodeFactory的节点
比使用文档
更有效,因为NodeFactory从XML缓存中提取其信息,并且不像文档
那样每次调用数据库。使用NodeFactory的唯一缺点是它只包含那些已发布的节点,但通常您只希望使用这些节点。看
Edit:在做了一些修改之后,我发现
Document
已经包含了一个getsubstands()
方法,该方法返回一个IEnumerable
,这就是为什么我们必须执行.Cast()
。因此,如果您选择仍然使用文档
,似乎可以避免创建扩展方法。否则,如果您仍要使用类似上述扩展方法的内容,则需要将其重命名为其他内容。文档的类型是否高于Umbraco特定类型?是的。作为业务逻辑的一部分,您是否有可能建立文档文件夹结构的缓存,并在缓存中执行快速查找?如何检索根节点(节点
)?也许你可以通过它们的文档类型查询叶节点
?谢谢,@MarkusJarderot,但是你能再解释一下你的意思吗?第一次使用Umbraco和C#,感觉一切都是一个节点!文档
类型是否高于Umbraco特定类型?是的。业务的一部分