Software Developers
Showing results for 
Search instead for 
Do you mean 

Auto Discovery of build order problems in c# solutions

amitbet ‎11-28-2013 02:33 AM - edited ‎11-28-2013 02:37 AM


Some background:

When developing a large scale project, C# Solutions quickly become laden with too many proj files, so when loading a single monolithic solution starts slowing down developer progress, there are several approaches which can be taken:

  1. Dividing the project into several separate parts by using separate solutions which reference each other by dll reference, while using project references internally. (Multi Solution)
  2. Having one solution for compilation + small solutions per feature/team (Partitioned Single Solution)
  3. Using dll references across the board and allowing solutions to be created by need.

You can read more about the different solution construction methods and microsoft's recommendations in the article about solution construction methods on msdn.


In our c# solutions we use dll referencing (option 3), this method has some benefits like allowing for small solutions to be created on the fly for a team or a feature.


The problem

This approach has one downside: you need to maintain the solution’s internal dependency tree by yourself, by adding a dependency definition to the solution for each same-solution project who's dll is referenced, this allows the studio to construct a build order tree, which prevets a project from compiling before it's dependencies are built.

as we all know manual management of such a structure is prone to neglect which leads to intermittent build errors depending on whether you are compiling a clean build (which is always done on the build server), or have old version of dlls you can depend on (in which case other api-change related problems can arise)


Compiling C# in vs2012 is multi-threaded, this increases the chance for a project to be compiled before it's dependencies so the problem becomes even more apparentKnowing of such problems in advance, can prevent the build from breaking multiple times until you finally get it right.

Using solutions based on Partitioned Single Solution (option 2) will also lead you into the same dependency tree problems I faced.


Now, if you are thinking: “nobody builds their solution this way”, you obviously are not working on an enterprise scale c# project, and so you can count your blessings and move on to read one of my other postings, which deal with more core c# oriented matters, but as this is not the first project on which I have encountered the problem (& not the first company too), I imagine that this can help those of you who remain with me after this point.

I ended up writing a small program to detect these annoying errors for me:






This detects the problem by:

  1. Mapping the assembly names of all the projects (parsing the solution + proj files)
  2. Searching through the project references to find references to dlls
  3. Taking only the dlls that are created within the solution
  4. Removing dll references that already have manually defined solution dependencies
  5. Reporting what we found.

Automatic correction is very possible, but I doubt it is worth the effort of implementing so I will leave this as an exercise for any of you who are willing and able.



This is how this is actually done in code: (look at the comments inside the code) 

  private void btnRun_Click(object sender, RoutedEventArgs e)
            //parse the solution (dll refs which have a manual dependency defined are treated as project dependencies)
            SolutionInfo sln = new SolutionInfo(txtSolution.Text, ParseProjectsMethod.ParseFull);
            //get all assembly names in solution (lower case)
            var assemblyNames = sln.ProjectsInSolution.Select(p => p.Value.AssemblyNameOnDisk.ToLower());

            //identify dlls which were supposed to be references
            Dictionary<ProjectInfo, IEnumerable<ProjectInfo>> missingDependencies = new Dictionary<ProjectInfo, IEnumerable<ProjectInfo>>();
            var projects = sln.ProjectsInSolution.Values;
            foreach (var proj in projects)
                //DependsOnDlls means only the dll references (if dependency was manually defined already it is considered a proj ref)
                var missingDependencyAssemblyNames = proj.DependsOnDlls.Where(dllName => assemblyNames.Contains(dllName.ToLower()));
                //get more data for the found problems by getting full project information for each project involved.
                if (missingDependencyAssemblyNames.Count() > 0)
                    List<ProjectInfo> missingProjs = new List<ProjectInfo>();
                    missingDependencyAssemblyNames.ToList().ForEach(d => missingProjs.Add(projects.First(p => p.AssemblyNameOnDisk.ToLower() == d.ToLower())));
                    missingDependencies.Add(proj, missingProjs);
            //format the missing items as strings and display in the listbox
            MainVM vm = (MainVM)this.DataContext;
            foreach (var key in missingDependencies.Keys)
                var refList = missingDependencies[key];
                foreach (var ref1 in refList)
                    vm.MissingDependenciesList.Add(key.Name + " --> " + ref1.Name);


About the code:

I have written my own parser for the solution and project files some time back, and I have been using them ever since for several other projects. The part about treating the dll references with manual dependencies defined is also something I’ve already done as part of the solution parsing (which contains the dependency definition when manually defined) so the rest was easy.

Download project 



I hope you find this useful, as I know I did, I would think this kind of check should have been part of the visual studio to begin with, and maybe show up as a warning or an error in order to save you the trouble of debugging these sporadic compilation order problems later on. Now you take it out for a spin, and tell me how it works for you.


0 Kudos
About the Author


I've been all over the coding world since earning my degrees have worked several years in c++ and then several in java, finally setteling into c# about 7 years ago, where i spent a good amount of my time in Performance tweaking &amp; memory debugging, as well as designing new solutions and hacking at old ones to stay in line. Computers never cease to amaze me, and i'm glad to have found a field where i get paid to do what i enjoy. some of my tools and thoughts are also stored in codeproject, and you are welcome to check them out there.

Nov 29 - Dec 1
Discover 2016 London
Learn how to thrive in a world of digital transformation at our biggest event of the year, Discover 2016 London, November 29 - December 1.
Read more
Each Month in 2016
Software Expert Days - 2016
Join us online to talk directly with our Software experts during online Expert Days. Find information here about past, current, and upcoming Expert Da...
Read more
View all