【问题标题】:Looping through DirectoryEntry or any object hierarchy - C#遍历 DirectoryEntry 或任何对象层次结构 - C#
【发布时间】:2009-04-01 16:55:30
【问题描述】:

我目前正在开发一个应用程序,该应用程序使用 System.DirectoryServices 命名空间来创建 DirectoryEntry 对象并遍历整个层次结构以收集信息。

我不知道层次结构中每个 DirectoryEntry 对象的子条目数,因此我无法通过 Children 属性为蜘蛛创建 N 个嵌套循环

这是我的伪代码示例:

//root directory
DirectoryEntry root = new DirectoryEntry(path);

if(DirectoryEntry.Childern != null)
{
    foreach(DirectoryEntry child in root.Children)
    {
        //loop through each Children property unitl I reach the last sub directory
    }
}

我的问题是,如果您不知道对象中子目录的数量,那么创建循环以收集信息的最佳方法是什么?

(这可以应用于你不知道对象层次结构的任何类型的对象)

【问题讨论】:

    标签: c# loops hierarchy web-crawler directoryservices


    【解决方案1】:

    如果您不知道层次结构的深度并且需要向下遍历所有级别,请使用递归函数。 下面是一个使用深度优先遍历的例子。

    using (DirectoryEntry root = new DirectoryEntry(someDN))
    {
        DoSomething(root);
    }
    
    
    function DoSomething(DirectoryEntry de)
    {
        // Do some work here against the directory entry
    
        if (de.Children != null)
        {
            foreach (DirectoryEntry child in de.Children)
            {
                using (child)
                {
                    DoSomething(child);
                }
            }
        }
    }
    

    或者,无需递归,您可以通过添加队列或堆栈数据结构并存储您已经看到但尚未访问的对象来进行遍历。

    Queue<DirectoryEntry> queue = new Queue<DirectoryEntry>();
    DirectoryEntry root = new DirectoryEntry(someDN);
    queue.Add(root);
    
    while (queue.Any())
    {
        using (DirectoryEntry de = queue.Dequeue())
        {
            // Do some work here against the directory entry
    
            if (de.Children != null)
            {
                foreach (DirectoryEntry child in de.Children)
                {
                    queue.Enqueue(child);
                }
            }
        }
    }
    

    【讨论】:

    • 顺便说一句,这是一个很好的例子,说明递归实际上是处理问题的好方法。因为文件系统本身施加了深度限制,所以您不应该破坏堆栈。但是,您必须小心,以防树中存在循环链接...
    • @jeffmaphone:DirectoryEntry 实际上将指向 LDAP 服务器,而不是文件系统。我不确定 LDAP 深度限制,但如果存在循环,处理它的最简单方法是记录您访问的每个条目的 GUID,如果您访问同一条目两次,则停止递归。
    • 在 foreach 循环中使用using(child){...}确保自己清理。见stackoverflow.com/questions/41378746/disposing-during-foreach/…
    • @Born2Smile 好点。更新了此处的代码示例并妥善处理。
    【解决方案2】:

    你必须把递归函数写成...

    DirectoryEntry root = new DirectoryEntry(path);
    DoForEveryNode(root);
    
    void DoForEveryNode(DirectoryEntry node)
    {
        // do something..
    
        foreach(DirectoryEntry child in node.Children)
        {
            DoForEveryNode(child);
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用递归调用子级的函数。 退出条件:没有更多的孩子等。

      【讨论】:

        【解决方案4】:

        一种选择是使用递归。将该代码设置在一个函数中,然后在 foreach 循环中调用自身,每次都传递下一个目录(子项)

        【讨论】:

          【解决方案5】:

          欢迎来到递归的奇妙世界。您需要一个接受 Directory 作为参数的函数。给定该目录,它会查找所有子目录,并为每个子目录...调用自身。

          【讨论】:

            猜你喜欢
            • 2011-09-23
            • 1970-01-01
            • 2011-08-18
            • 1970-01-01
            • 2012-04-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-02-28
            相关资源
            最近更新 更多