/// <summary> /// Retrieves all depending modules of the specified module recursively and checks for circular dependencies. /// </summary> /// <param name="module">Code generation module to retrieve depending modules for.</param> /// <param name="alreadyProcessedModules">Modules that have already been processed.</param> /// <returns>Code generation modules that depend on the specified module.</returns> private static HashSet <ICodeGenModule> GetDependingModules(ICodeGenModule module, HashSet <ICodeGenModule> alreadyProcessedModules) { HashSet <ICodeGenModule> complete = new HashSet <ICodeGenModule>(IdentityComparer <ICodeGenModule> .Default); // add all modules the current module depends on and check for circular dependencies foreach (ICodeGenModule dependency in module.Dependencies) { // check whether the depending module has already been processed, which would indicate a circular dependency if (alreadyProcessedModules.Contains(dependency, IdentityComparer <ICodeGenModule> .Default)) { string error = string.Format("Module ({0}) is referenced circularly.", dependency.ToString()); throw new CodeGenException(error); } // add the current module to the 'processed' set to indicate that it is already part of the dependency chain // (depending module may not reference a module already listed there => circular dependency check) HashSet <ICodeGenModule> processed = new HashSet <ICodeGenModule>(alreadyProcessedModules, IdentityComparer <ICodeGenModule> .Default) { dependency }; // resolve dependencies and merge depending modules into the complete set of modules taking part HashSet <ICodeGenModule> dependencies = GetDependingModules(dependency, processed); complete.UnionWith(dependencies); complete.Add(dependency); } return(complete); }
/// <summary> /// Adds a code generation module contributing to the type to create. /// </summary> /// <param name="module">Module to add.</param> public void AddModule(ICodeGenModule module) { if (module == null) { throw new ArgumentNullException(nameof(module)); } if (mSortedModules.Find(other => object.ReferenceEquals(other, module)) != null) { throw new CodeGenException("The specified module is already part of the type definition."); } // update list of modules // (ResolveModuleDependencies() can throw CodeGenException, if it detects a circular module dependency) List <ICodeGenModule> modules = new List <ICodeGenModule>(mSortedModules); modules.Add(module); mSortedModules = new List <ICodeGenModule>(ResolveModuleDependencies(modules)); }