PageRenderTime 28ms CodeModel.GetById 12ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/V4/PrismLibrary/Desktop/Prism/Modularity/ModuleDependencySolver.cs

#
C# | 169 lines | 108 code | 19 blank | 42 comment | 16 complexity | 11cc2a7974e1c7c5815e4eca486577ef MD5 | raw file
  1//===================================================================================
  2// Microsoft patterns & practices
  3// Composite Application Guidance for Windows Presentation Foundation and Silverlight
  4//===================================================================================
  5// Copyright (c) Microsoft Corporation.  All rights reserved.
  6// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
  7// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
  8// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  9// FITNESS FOR A PARTICULAR PURPOSE.
 10//===================================================================================
 11// The example companies, organizations, products, domain names,
 12// e-mail addresses, logos, people, places, and events depicted
 13// herein are fictitious.  No association with any real company,
 14// organization, product, domain name, email address, logo, person,
 15// places, or events is intended or should be inferred.
 16//===================================================================================
 17using System;
 18using System.Collections.Generic;
 19using System.Globalization;
 20using Microsoft.Practices.Prism.Properties;
 21
 22namespace Microsoft.Practices.Prism.Modularity
 23{
 24    /// <summary>
 25    /// Used by <see cref="ModuleInitializer"/> to get the load sequence
 26    /// for the modules to load according to their dependencies.
 27    /// </summary>
 28    public class ModuleDependencySolver
 29    {
 30        private readonly ListDictionary<string, string> dependencyMatrix = new ListDictionary<string, string>();
 31        private readonly List<string> knownModules = new List<string>();
 32
 33        /// <summary>
 34        /// Adds a module to the solver.
 35        /// </summary>
 36        /// <param name="name">The name that uniquely identifies the module.</param>
 37        public void AddModule(string name)
 38        {
 39            if (String.IsNullOrEmpty(name))
 40                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.StringCannotBeNullOrEmpty, "name"));
 41
 42            AddToDependencyMatrix(name);
 43            AddToKnownModules(name);
 44        }
 45
 46        /// <summary>
 47        /// Adds a module dependency between the modules specified by dependingModule and
 48        /// dependentModule.
 49        /// </summary>
 50        /// <param name="dependingModule">The name of the module with the dependency.</param>
 51        /// <param name="dependentModule">The name of the module dependingModule
 52        /// depends on.</param>
 53        public void AddDependency(string dependingModule, string dependentModule)
 54        {
 55            if (String.IsNullOrEmpty(dependingModule))
 56                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.StringCannotBeNullOrEmpty, "dependingModule"));
 57
 58            if (String.IsNullOrEmpty(dependentModule))
 59                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.StringCannotBeNullOrEmpty, "dependentModule"));
 60
 61            if (!knownModules.Contains(dependingModule))
 62                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.DependencyForUnknownModule, dependingModule));
 63
 64            AddToDependencyMatrix(dependentModule);
 65            dependencyMatrix.Add(dependentModule, dependingModule);
 66        }
 67
 68        private void AddToDependencyMatrix(string module)
 69        {
 70            if (!dependencyMatrix.ContainsKey(module))
 71            {
 72                dependencyMatrix.Add(module);
 73            }
 74        }
 75
 76        private void AddToKnownModules(string module)
 77        {
 78            if (!knownModules.Contains(module))
 79            {
 80                knownModules.Add(module);
 81            }
 82        }
 83
 84        /// <summary>
 85        /// Calculates an ordered vector according to the defined dependencies.
 86        /// Non-dependant modules appears at the beginning of the resulting array.
 87        /// </summary>
 88        /// <returns>The resulting ordered list of modules.</returns>
 89        /// <exception cref="CyclicDependencyFoundException">This exception is thrown
 90        /// when a cycle is found in the defined depedency graph.</exception>
 91        public string[] Solve()
 92        {
 93            List<string> skip = new List<string>();
 94            while (skip.Count < dependencyMatrix.Count)
 95            {
 96                List<string> leaves = this.FindLeaves(skip);
 97                if (leaves.Count == 0 && skip.Count < dependencyMatrix.Count)
 98                {
 99                    throw new CyclicDependencyFoundException(Resources.CyclicDependencyFound);
100                }
101                skip.AddRange(leaves);
102            }
103            skip.Reverse();
104
105            if (skip.Count > knownModules.Count)
106            {
107                string moduleNames = this.FindMissingModules(skip);
108                throw new ModularityException(moduleNames, String.Format(CultureInfo.CurrentCulture,
109                                                            Resources.DependencyOnMissingModule,
110                                                            moduleNames));
111            }
112
113            return skip.ToArray();
114        }
115
116        private string FindMissingModules(List<string> skip)
117        {
118            string missingModules = "";
119
120            foreach (string module in skip)
121            {
122                if (!knownModules.Contains(module))
123                {
124                    missingModules += ", ";
125                    missingModules += module;
126                }
127            }
128
129            return missingModules.Substring(2);
130        }
131
132        /// <summary>
133        /// Gets the number of modules added to the solver.
134        /// </summary>
135        /// <value>The number of modules.</value>
136        public int ModuleCount
137        {
138            get { return dependencyMatrix.Count; }
139        }
140
141        private List<string> FindLeaves(List<string> skip)
142        {
143            List<string> result = new List<string>();
144
145            foreach (string precedent in dependencyMatrix.Keys)
146            {
147                if (skip.Contains(precedent))
148                {
149                    continue;
150                }
151
152                int count = 0;
153                foreach (string dependent in dependencyMatrix[precedent])
154                {
155                    if (skip.Contains(dependent))
156                    {
157                        continue;
158                    }
159                    count++;
160                }
161                if (count == 0)
162                {
163                    result.Add(precedent);
164                }
165            }
166            return result;
167        }
168    }
169}