Click here to Skip to main content
15,896,111 members
Articles / Programming Languages / C#

Visualizing Project Dependencies Automatically

Rate me:
Please Sign up or sign in to vote.
4.09/5 (11 votes)
4 Sep 2007CPOL3 min read 43.1K   428   32  
Have a large code tree? Wondering which projects refer to which other ones? Manually run this console app, schedule it to run nightly or after each build.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;

namespace CompanyName.DependencyTracker
{
    /// <summary>
    /// A single project
    /// </summary>
    public class Project
    {
        /// <summary>
        /// Given a file path for a project file, load it in
        /// </summary>
        /// <param name="FolderPath"></param>
        public Project(string ProjectPath)
        {
            FileInfo projectInfo = new FileInfo(ProjectPath);
            if (projectInfo.Extension != ".csproj") throw new ArgumentException("Extension " + projectInfo.Extension + " is not valid");

            _Name = projectInfo.Name.Replace(projectInfo.Extension, ""); //remove extension from file name
            _ProjectPath = ProjectPath;

            //load referenced projects
            string[] ReferenceProjectPaths = GetReferenceProjectPaths();
            foreach (string path in ReferenceProjectPaths)
                _ReferencedProjects.Add(new Project(path));
        }

        /// <summary>
        /// Load project file from disk and get list of project paths
        /// </summary>
        /// <returns></returns>
        private string[] GetReferenceProjectPaths()
        {
            XmlDocument project = new XmlDocument();
            project.Load(ProjectPath);
            XmlNamespaceManager namespaceManager = new XmlNamespaceManager(project.NameTable);
            namespaceManager.AddNamespace("ns", "http://schemas.microsoft.com/developer/msbuild/2003");

            List<string> returnItems = new List<string>();
            //couldn't get default namespace to work, had to use ns and then prefix all nodes with it
            XmlNodeList referenceNodes = project.SelectNodes("//ns:Project/ns:ItemGroup/ns:Reference/ns:HintPath", namespaceManager);
            foreach (XmlNode node in referenceNodes)
            {
                //start from location of project file since hint path is relative to there
                Directory.SetCurrentDirectory(new FileInfo(ProjectPath).Directory.FullName);

                //reference in project file will be to dll, we need to get project file location
                FileInfo refDLL = new FileInfo(node.InnerText);

                //if the reference is to the immediate references directory then it is probably a straight DLL reference
                if (node.InnerText.StartsWith("..\\References")) continue;

                //move to relative location
                string CurrentDirectory = refDLL.Directory.Parent.FullName;
                if (Directory.Exists(CurrentDirectory))
                    Directory.SetCurrentDirectory(CurrentDirectory);
                else
                    continue; //sometimes hintpaths are bad, in this case just go to next one

                //assume name of file - extension is name of project for now
                string ProjectName = refDLL.Name.Replace(refDLL.Extension, "");
                string ProjectFilePath = ""; //init to nothing initially
                string[] ProjectFilePaths = Directory.GetFiles(Directory.GetCurrentDirectory(), ProjectName + ".csproj", SearchOption.AllDirectories);
                if(ProjectFilePaths == null || ProjectFilePaths.GetUpperBound(0) < 0)
                {
                    //if we don't have anything, check if the dll is called x.y.z.projectname but the file is just projectname.csproj
                    int dotPos = ProjectName.LastIndexOf('.');
                    if (dotPos != -1)
                    {
                        ProjectName = ProjectName.Substring(dotPos + 1); //start after the last dot
                        ProjectFilePaths = Directory.GetFiles(Directory.GetCurrentDirectory(), ProjectName + ".csproj", SearchOption.AllDirectories);
                    }
                } 

                //if anything found, use it
                //TODO: Should we raise an event here to let people know we couldn't find a project?
                if((ProjectFilePaths != null && ProjectFilePaths.GetUpperBound(0) >= 0))
                    ProjectFilePath = ProjectFilePaths[0]; //get first match

                //if something found add to list
                if(!String.IsNullOrEmpty(ProjectFilePath))
                    //get first match on project file
                    returnItems.Add(ProjectFilePath);
            }

            return returnItems.ToArray();
        }

        private ProjectList _ReferencedProjects = new ProjectList();

        /// <summary>
        /// All projects that the current project references
        /// </summary>
        public ProjectList ReferencedProjects
        {
            get { return _ReferencedProjects; }
            set { _ReferencedProjects = value; }
        }

        private string _Name = "";

        /// <summary>
        /// Name of the current project
        /// </summary>
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        private string _ProjectPath = "";

        /// <summary>
        /// Path to the project file
        /// </summary>
        public string ProjectPath
        {
            get { return _ProjectPath; }
            set { _ProjectPath = value; }
        }
    }

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
I've been a software developer since 1996 and have enjoyed C# since 2003. I have a Bachelor's degree in Computer Science and for some reason, a Master's degree in Business Administration. I currently do software development contracting/consulting.

Comments and Discussions