Perhaps I am just having my dumb moment right now. I have the following:
List<DirectoryEntry> list = new List<DirectoryEntry>();
List.Add(startEntry);
int i=0;
while(i < list.Count) {
DirectoryEntry entry = list[i];
foreach(DirectoryEntry child in GetChildEntries(entry)) {
if(!list.Contains(child)) // Do not add if entry already in list!
list.Add(child);
}
}
This does not work because Contains somehow returns false for two directoryEntries that point to the same AD object.
So I thought to make a Dictionary from that and store the distinguishedName along with the entry:
Dictionary<string,DirectoryEntry> list = new Dictionary<string,DirectoryEntry>();
List.Add(startEntry.Properties["distinguishedName"].Value,startEntry);
int i=0;
while(i < list.Count) {
DirectoryEntry entry = list[i]; // Does not work, because the index is a string here.
// How to get the ith entry from the dictionary?
foreach(DirectoryEntry child in GetChildEntries(entry)) {
var dn = child.Properties["distinguishedName"].Value;
if(!list.ContainsKey(dn)) list.Add(dn,child);
}
}
The question, as stated in the code comment:
How to get the ith entry from the dictionary?
Well you can use list.ElementAt(i)
to get the ith element in the order they happen to be returned by the dictionary - but there's no guarantee as to what order that is, or that it will stay consistent over time. I would strongly recommend avoiding thinking of a dictionary has having any concept of order.
It seems to me that you just need to iterate over the dictionary though:
foreach (var entry in list)
{
...
}
That leads to another problem though, which is that you're modifying the collection you're iterating over while you're iterating over it, which will fail. You might want to consider creating a new dictionary while you're iterating, and then add all the entries to the original one afterwards.
It's unclear whether you really want a dictionary or not though. We don't know what you're really trying to achieve - there are many different options here.
EDIT: If you want to flatten, you could do something like:
var entries = new Dictionary<string, DirectoryEntry>();
var queue = new Queue<DirectoryEntry>();
queue.Enqueue(startEntry);
while (queue.Count > 0)
{
var candidate = queue.Dequeue();
string key = candidate.Properties["distinguishedName"].Value;
if (!entries.ContainsKey(key))
{
entries[key] = candidate;
foreach (var child in GetChildEntries(candidate))
{
queue.Enqueue(child);
}
}
}
You could "hide" the foreach
loop by creating your own EnqueueAll
extension method on Queue<T>
, if you wanted.
This feels to me like simpler code to understand than iterating over a collection you're still adding to.
EDIT: And if you don't need to look up by distinguished name later, you can use a HashSet<DirectoryEntry>
with a custom equality comparer:
var entries = new HashSet<DirectoryEntry>(new DirectoryEntryEqualityComparer());
var queue = new Queue<DirectoryEntry>();
queue.Enqueue(startEntry);
while (queue.Count > 0)
{
if (entries.Add(candidate))
{
foreach (var child in GetChildEntries(candidate))
{
queue.Enqueue(child);
}
}
}
See more on this question at Stackoverflow