HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Managing tree nodes

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
nodesmanagingtree

Problem

I have complex logic manage EnvDTE.Project and EnvDTE.ProjectItem for a VS Addin (VS 2010).

I would like elegant, easily maintainable code that follows DRY and KISS principles. Maybe using helper with Action or Func methods.

I want a Dictionary, for access by "Key" (an Id, the name of a projectItem).

And now I have 5 lists: List.

Maybe for more performance I could use 5 lists or one list for all, and entity ItemBranchable will have a Type property, and using Linq to filter it by Type.

Full source code:

```
public partial class ModelBranchingMerging
{
private static ModelBranchingMerging Instance = null;

public static ModelBranchingMerging GetModel(Project project)
{
if (Instance == null)
{
Instance = new ModelBranchingMerging();
Instance.NavigateProject(project);
}
return Instance;
}

private ModelBranchingMerging()
{
Data = new Dictionary();
Forms = new List();
Packages = new List();
PackagesBodies = new List();
Types = new List();
TypesBodies = new List();
}

public Dictionary Data { get; set; }
public List Forms { get; set; }
public List Packages { get; set; }
public List PackagesBodies { get; set; }
public List Types { get; set; }
public List TypesBodies { get; set; }

// OMMITTED
private void NavigateProjectItems(ProjectItems colProjectItems)
{
if (colProjectItems == null) return;

foreach (EnvDTE.ProjectItem objProjectItem in colProjectItems)
{
if ((objProjectItem.Collection.Parent as ProjectItem) != null)
{
var parentName = ((ProjectItem)objProjectItem.Collection.Parent).Name;

var itemBranchable = new ItemBranchable(objProjectItem);

Solution

You almost gave the answer by yourself:


Maybe for more performance I could use 5 lists or one list for all,
and entity ItemBranchable will have a Type property, and using Linq to
filter it by Type.

Everytime I need to separate a collection of objects I insert them in the same list and then filter them by type. You can also put them in a dictionary, that is better if you are filtering the objects by type many times. Although sometimes the best thing you can do is to have a second look in your code, in most cases there is a design pattern that you could apply and you wouldn't have this issue in first place.

private ModelBranchingMerging()
{
    Data = new List();
}

public ICollection Data { get; set; }
public IEnumerable Forms 
    get{
        return Data.Where(d => d.Parent == Operaciones.FolderForms);
    }
}
//so on so forth

//and your NavigateProjectItems implementation:

private void NavigateProjectItems(ProjectItems colProjectItems)
    {
        if (colProjectItems == null) return;

        foreach (EnvDTE.ProjectItem objProjectItem in colProjectItems)
        {
            var parentProjectItem = (objProjectItem.Collection.Parent as ProjectItem);
            if (parentProjectItem != null)
            {
                var parentName = parentProjectItem.Name;
                var itemBranchable = new ItemBranchable(parentProjectItem);
                Data.Add(itemBranchable); 
            }

            if (objProjectItem.SubProject != null)
            {
                NavigateProject(objProjectItem.SubProject);
            }
            else
            {
                NavigateProjectItems(objProjectItem.ProjectItems);
            }

        }
    }


Notice that I had your foreach body a bit modified, I'll be stating some good practices that you should follow:

  • If you need to perform a cast, do so on a separate statement with the as operator (that you already used).



  • If a cast is made always use the variable with the most specific type in the remaining implementation (if applicable, in this case you can't to this to call the method recursively).



Like I said you could also make use of a dictionary, it's pretty easy to make a to group the items by type with linq:

public class KeyValue{
    public int Key{get;set;}
    public string Value{get;set;}
}

void Main()
{
    List list = new List();
    list.Add(new KeyValue(){Key = 1, Value = "1.1"});
    list.Add(new KeyValue(){Key = 1, Value = "1.2"});
    list.Add(new KeyValue(){Key = 1, Value = "1.3"});
    list.Add(new KeyValue(){Key = 2, Value = "2.1"});
    list.Add(new KeyValue(){Key = 2, Value = "2.2"});
    IDictionary> map = list
        .GroupBy(item => item.Key)
        .ToDictionary(g => g.Key, v => v.ToList());
}

Code Snippets

private ModelBranchingMerging()
{
    Data = new List<ItemBranchable>();
}

public ICollection<ItemBranchable> Data { get; set; }
public IEnumerable<ItemBranchable> Forms 
    get{
        return Data.Where(d => d.Parent == Operaciones.FolderForms);
    }
}
//so on so forth

//and your NavigateProjectItems implementation:

private void NavigateProjectItems(ProjectItems colProjectItems)
    {
        if (colProjectItems == null) return;

        foreach (EnvDTE.ProjectItem objProjectItem in colProjectItems)
        {
            var parentProjectItem = (objProjectItem.Collection.Parent as ProjectItem);
            if (parentProjectItem != null)
            {
                var parentName = parentProjectItem.Name;
                var itemBranchable = new ItemBranchable(parentProjectItem);
                Data.Add(itemBranchable); 
            }

            if (objProjectItem.SubProject != null)
            {
                NavigateProject(objProjectItem.SubProject);
            }
            else
            {
                NavigateProjectItems(objProjectItem.ProjectItems);
            }

        }
    }
public class KeyValue{
    public int Key{get;set;}
    public string Value{get;set;}
}

void Main()
{
    List<KeyValue> list = new List<KeyValue>();
    list.Add(new KeyValue(){Key = 1, Value = "1.1"});
    list.Add(new KeyValue(){Key = 1, Value = "1.2"});
    list.Add(new KeyValue(){Key = 1, Value = "1.3"});
    list.Add(new KeyValue(){Key = 2, Value = "2.1"});
    list.Add(new KeyValue(){Key = 2, Value = "2.2"});
    IDictionary<int, List<KeyValue>> map = list
        .GroupBy(item => item.Key)
        .ToDictionary(g => g.Key, v => v.ToList());
}

Context

StackExchange Code Review Q#71414, answer score: 2

Revisions (0)

No revisions yet.