patterncsharpMinor
Building tree structure based on flat objects
Viewed 0 times
objectsbuildingflatstructurebasedtree
Problem
You can find here a Follow-up question
Description
A
The root objects
The goal of the given class below is to build a
The class in question
```
public class ArchiveBuilder
{
public static List Build(List entries)
{
List rootArchiveTreeEntries = new List();
if (entries != null && entries.Count > 0)
{
List rootEntries = GetRootEntries(entries);
foreach (ArchiveDefinition definition in rootEntries)
{
rootArchiveTreeEntries.Add(new ArchiveTreeEntry(definition));
entries.Remove(definition);
}
foreach (ArchiveTreeEntry parent in rootArchiveTreeEntries)
{
FillChildren(parent, entries);
}
}
return rootArchiveTreeEntries;
}
private static void FillChildren(ArchiveTreeEntry parent,
List entries)
{
if (entries.Count > 0)
{
List children = GetChildren(entries, parent.Id);
if (children.Count > 0)
{
RemoveChildren(entries, parent.Id);
foreach (ArchiveDefinition child in children)
{
ArchiveTreeEntry treeEntryChild = new ArchiveTreeEntry(child);
parent.AddChild(treeEntryChild);
FillChildren(treeEntryChild, entries);
}
}
}
}
private static List GetRootEntries(List entries)
{
return entries.FindAll(e => e.TypeOfArchive == ArchiveType.Archive);
}
private static List GetChildren(List entries, string parentID)
Description
A
List is returned by a 3rd party webservice, which will then be transformed to a List. These ArchiveDefinition objects are connected by Parent'.ArchiveNodeId == 'Child'.ParentId.The root objects
TypeOfArchive property will always have the value ArchiveType.Archive.The goal of the given class below is to build a
List of these flat object list to fill a treeview control. The class in question
```
public class ArchiveBuilder
{
public static List Build(List entries)
{
List rootArchiveTreeEntries = new List();
if (entries != null && entries.Count > 0)
{
List rootEntries = GetRootEntries(entries);
foreach (ArchiveDefinition definition in rootEntries)
{
rootArchiveTreeEntries.Add(new ArchiveTreeEntry(definition));
entries.Remove(definition);
}
foreach (ArchiveTreeEntry parent in rootArchiveTreeEntries)
{
FillChildren(parent, entries);
}
}
return rootArchiveTreeEntries;
}
private static void FillChildren(ArchiveTreeEntry parent,
List entries)
{
if (entries.Count > 0)
{
List children = GetChildren(entries, parent.Id);
if (children.Count > 0)
{
RemoveChildren(entries, parent.Id);
foreach (ArchiveDefinition child in children)
{
ArchiveTreeEntry treeEntryChild = new ArchiveTreeEntry(child);
parent.AddChild(treeEntryChild);
FillChildren(treeEntryChild, entries);
}
}
}
}
private static List GetRootEntries(List entries)
{
return entries.FindAll(e => e.TypeOfArchive == ArchiveType.Archive);
}
private static List GetChildren(List entries, string parentID)
Solution
-
You could use the
-
You have made the public method
in app
-
That said, the private methods are fine as static methods because the are an implementation detail.
-
From there, you could then re-write the method above to be:
So here is the completely re-written class:
NB: I haven't compiled the class or tested it, so it might not work out the box.
You could use the
AddRange combined with the Except method inside of Build:public static List Build(List entries)
{
List rootArchiveTreeEntries = new List();
if (entries != null && entries.Count > 0)
{
List rootEntries = GetRootEntries(entries);
entries = rootArchiveTreeEntried.AddRange(rootEntries.Select(definition=> new ArchiveTreeEntry(definition)).Except(entries);
foreach (ArchiveTreeEntry parent in rootArchiveTreeEntries)
{
FillChildren(parent, entries);
}
}
return rootArchiveTreeEntries;
}-
You have made the public method
static, which in this case is probably fine but it does make it harder to unit test dependencies. I envisage the class being consumed, like this:in app
var builder = new ArchiveBuilder();
builder.Build(entities);-
That said, the private methods are fine as static methods because the are an implementation detail.
- The private methods can return/accept
IEnumerable<>instead ofList<>
-
From there, you could then re-write the method above to be:
public static List Build(List entries)
{
List rootArchiveTreeEntries = new List();
if (entries != null && entries.Count > 0)
{
entries = rootArchiveTreeEntried.AddRange(GetRootEntries(entries).Select(entry => new ArchiveTreeEntry(definition)).Except(entries);
foreach (ArchiveTreeEntry parent in rootArchiveTreeEntries)
{
FillChildren(parent, entries);
}
}
return rootArchiveTreeEntries;
}So here is the completely re-written class:
public class ArchiveBuilder
{
public IEnumerable Build(IEnumerable entries)
{
IEnumerable rootArchiveTreeEntries = new List();
if (entries != null && entries.Count > 0)
{
entries = rootArchiveTreeEntried.AddRange(GetRootEntries(entries).Select(entry => new ArchiveTreeEntry(definition)).Except(entries);
foreach (ArchiveTreeEntry parent in rootArchiveTreeEntries)
{
FillChildren(parent, entries);
}
}
return rootArchiveTreeEntries;
}
private static void FillChildren(ArchiveTreeEntry parent,
IEnumerable entries)
{
if (entries.Count > 0)
{
IEnumerable children = GetChildren(entries, parent.Id);
if (children.Count > 0)
{
RemoveChildren(entries, parent.Id);
foreach (ArchiveDefinition child in children)
{
ArchiveTreeEntry treeEntryChild = new ArchiveTreeEntry(child);
parent.AddChild(treeEntryChild);
FillChildren(treeEntryChild, entries);
}
}
}
}
private static IEnumerable GetRootEntries(IEnumerable entries)
{
return entries.FindAll(e => e.TypeOfArchive == ArchiveType.Archive);
}
private static IEnumerable GetChildren(IEnumerable entries, string parentID)
{
return entries.FindAll(e => e.ParentId == parentID);
}
private static void RemoveChildren(IEnumerable entries, string parentID)
{
entries.RemoveAll(e => e.ParentId == parentID);
}
}NB: I haven't compiled the class or tested it, so it might not work out the box.
Code Snippets
public static List<ArchiveTreeEntry> Build(List<ArchiveDefinition> entries)
{
List<ArchiveTreeEntry> rootArchiveTreeEntries = new List<ArchiveTreeEntry>();
if (entries != null && entries.Count > 0)
{
List<ArchiveDefinition> rootEntries = GetRootEntries(entries);
entries = rootArchiveTreeEntried.AddRange(rootEntries.Select(definition=> new ArchiveTreeEntry(definition)).Except(entries);
foreach (ArchiveTreeEntry parent in rootArchiveTreeEntries)
{
FillChildren(parent, entries);
}
}
return rootArchiveTreeEntries;
}var builder = new ArchiveBuilder();
builder.Build(entities);public static List<ArchiveTreeEntry> Build(List<ArchiveDefinition> entries)
{
List<ArchiveTreeEntry> rootArchiveTreeEntries = new List<ArchiveTreeEntry>();
if (entries != null && entries.Count > 0)
{
entries = rootArchiveTreeEntried.AddRange(GetRootEntries(entries).Select(entry => new ArchiveTreeEntry(definition)).Except(entries);
foreach (ArchiveTreeEntry parent in rootArchiveTreeEntries)
{
FillChildren(parent, entries);
}
}
return rootArchiveTreeEntries;
}public class ArchiveBuilder
{
public IEnumerable<ArchiveTreeEntry> Build(IEnumerable<ArchiveDefinition> entries)
{
IEnumerable<ArchiveTreeEntry> rootArchiveTreeEntries = new List<ArchiveTreeEntry>();
if (entries != null && entries.Count > 0)
{
entries = rootArchiveTreeEntried.AddRange(GetRootEntries(entries).Select(entry => new ArchiveTreeEntry(definition)).Except(entries);
foreach (ArchiveTreeEntry parent in rootArchiveTreeEntries)
{
FillChildren(parent, entries);
}
}
return rootArchiveTreeEntries;
}
private static void FillChildren(ArchiveTreeEntry parent,
IEnumerable<ArchiveDefinition> entries)
{
if (entries.Count > 0)
{
IEnumerable<ArchiveDefinition> children = GetChildren(entries, parent.Id);
if (children.Count > 0)
{
RemoveChildren(entries, parent.Id);
foreach (ArchiveDefinition child in children)
{
ArchiveTreeEntry treeEntryChild = new ArchiveTreeEntry(child);
parent.AddChild(treeEntryChild);
FillChildren(treeEntryChild, entries);
}
}
}
}
private static IEnumerable<ArchiveDefinition> GetRootEntries(IEnumerable<ArchiveDefinition> entries)
{
return entries.FindAll(e => e.TypeOfArchive == ArchiveType.Archive);
}
private static IEnumerable<ArchiveDefinition> GetChildren(IEnumerable<ArchiveDefinition> entries, string parentID)
{
return entries.FindAll(e => e.ParentId == parentID);
}
private static void RemoveChildren(IEnumerable<ArchiveDefinition> entries, string parentID)
{
entries.RemoveAll(e => e.ParentId == parentID);
}
}Context
StackExchange Code Review Q#58727, answer score: 2
Revisions (0)
No revisions yet.