PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/V1/spikes/AGCompositeApplicationLibrary/AGComposite/Modularity/ModuleDependencySolver.cs

#
C# | 169 lines | 107 code | 20 blank | 42 comment | 16 complexity | 3f6cfa1dbe9900458b449311a865be4b 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. //===============================================================================
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Globalization;
  20. using Microsoft.Practices.Composite.Properties;
  21. namespace Microsoft.Practices.Composite.Modularity
  22. {
  23. /// <summary>
  24. /// Used by <see cref="ModuleLoader"/> to get the load sequence
  25. /// for the modules to load according to their dependencies.
  26. /// </summary>
  27. public class ModuleDependencySolver
  28. {
  29. private readonly ListDictionary<string, string> dependencyMatrix = new ListDictionary<string, string>();
  30. private readonly List<string> knownModules = new List<string>();
  31. /// <summary>
  32. /// Adds a module to the solver.
  33. /// </summary>
  34. /// <param name="name">The name that uniquely identifies the module.</param>
  35. public void AddModule(string name)
  36. {
  37. if (String.IsNullOrEmpty(name))
  38. throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.StringCannotBeNullOrEmpty, "name"));
  39. AddToDependencyMatrix(name);
  40. AddToKnownModules(name);
  41. }
  42. /// <summary>
  43. /// Adds a module dependency between the modules specified by dependingModule and
  44. /// dependentModule.
  45. /// </summary>
  46. /// <param name="dependingModule">The name of the module with the dependency.</param>
  47. /// <param name="dependentModule">The name of the module dependingModule
  48. /// depends on.</param>
  49. public void AddDependency(string dependingModule, string dependentModule)
  50. {
  51. if (String.IsNullOrEmpty(dependingModule))
  52. throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.StringCannotBeNullOrEmpty, "dependingModule"));
  53. if (String.IsNullOrEmpty(dependentModule))
  54. throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.StringCannotBeNullOrEmpty, "dependentModule"));
  55. if (!knownModules.Contains(dependingModule))
  56. throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.DependencyForUnknownModule, dependingModule));
  57. AddToDependencyMatrix(dependentModule);
  58. dependencyMatrix.Add(dependentModule, dependingModule);
  59. }
  60. private void AddToDependencyMatrix(string module)
  61. {
  62. if (!dependencyMatrix.ContainsKey(module))
  63. {
  64. dependencyMatrix.Add(module);
  65. }
  66. }
  67. private void AddToKnownModules(string module)
  68. {
  69. if (!knownModules.Contains(module))
  70. {
  71. knownModules.Add(module);
  72. }
  73. }
  74. /// <summary>
  75. /// Calculates an ordered vector according to the defined dependencies.
  76. /// Non-dependant modules appears at the beginning of the resulting array.
  77. /// </summary>
  78. /// <returns>The resulting ordered list of modules.</returns>
  79. /// <exception cref="CyclicDependencyFoundException">This exception is thrown
  80. /// when a cycle is found in the defined depedency graph.</exception>
  81. public string[] Solve()
  82. {
  83. List<string> skip = new List<string>();
  84. while (skip.Count < dependencyMatrix.Count)
  85. {
  86. List<string> leaves = this.FindLeaves(skip);
  87. if (leaves.Count == 0 && skip.Count < dependencyMatrix.Count)
  88. {
  89. throw new CyclicDependencyFoundException();
  90. }
  91. skip.AddRange(leaves);
  92. }
  93. skip.Reverse();
  94. if (skip.Count > knownModules.Count)
  95. {
  96. throw new ModuleLoadException(String.Format(CultureInfo.CurrentCulture,
  97. Resources.DependencyOnMissingModule,
  98. FindMissingModules(skip)));
  99. }
  100. return skip.ToArray();
  101. }
  102. private string FindMissingModules(List<string> skip)
  103. {
  104. string missingModules = "";
  105. foreach (string module in skip)
  106. {
  107. if (!knownModules.Contains(module))
  108. {
  109. missingModules += ", ";
  110. missingModules += module;
  111. }
  112. }
  113. return missingModules.Substring(2);
  114. }
  115. /// <summary>
  116. /// Gets the number of modules added to the solver.
  117. /// </summary>
  118. /// <value>The number of modules.</value>
  119. public int ModuleCount
  120. {
  121. get { return dependencyMatrix.Count; }
  122. }
  123. private List<string> FindLeaves(List<string> skip)
  124. {
  125. List<string> result = new List<string>();
  126. foreach (string precedent in dependencyMatrix.Keys)
  127. {
  128. if (skip.Contains(precedent))
  129. {
  130. continue;
  131. }
  132. int count = 0;
  133. foreach (string dependent in dependencyMatrix[precedent])
  134. {
  135. if (skip.Contains(dependent))
  136. {
  137. continue;
  138. }
  139. count++;
  140. }
  141. if (count == 0)
  142. {
  143. result.Add(precedent);
  144. }
  145. }
  146. return result;
  147. }
  148. }
  149. }