Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // <Name>Avoid namespaces dependency cycles</Name>
- warnif count > 0
- // This query lists all application namespace dependency cycles.
- // Each row shows a different cycle, prefixed with a namespace entangled in the cycle.
- //
- // To browse a cycle on the dependency graph or the dependency matrix, right click
- // a cycle cell and export the matched namespaces to the dependency graph or matrix!
- //
- // In the matrix, dependency cycles are represented with red squares and black cells.
- // To easily browse dependency cycles, the Matrix comes with an option:
- // --> Display Direct and Indirect Dependencies
- //
- // Read our white books relative to partitioning code,
- // to know more about namespaces dependency cycles, and why avoiding them
- // is a simple but efficient solution to architecture for your code base.
- // http://www.ndepend.com/WhiteBooks.aspx
- // Optimization: restraint application assemblies set
- // If some namespaces are mutually dependent
- // - They must be declared in the same assembly
- // - The parent assembly must ContainsNamespaceDependencyCycle
- from assembly in Application.Assemblies
- .Where(a => a.ContainsNamespaceDependencyCycle != null &&
- a.ContainsNamespaceDependencyCycle.Value)
- // Optimization: restraint namespaces set
- // A namespace involved in a cycle necessarily have a null Level.
- let namespacesSuspect = assembly.ChildNamespaces.Where(n => n.Level == null)
- // hashset is used to avoid iterating again on namespaces already caught in a cycle.
- let hashset = new HashSet<INamespace>()
- from suspect in namespacesSuspect
- // By commenting in this line, the query matches all namespaces involved in a cycle.
- where !hashset.Contains(suspect)
- // Define 2 code metrics
- // - Namespaces depth of is using indirectly the suspect namespace.
- // - Namespaces depth of is used by the suspect namespace indirectly.
- // Note: for direct usage the depth is equal to 1.
- let namespacesUserDepth = namespacesSuspect.DepthOfIsUsing(suspect)
- let namespacesUsedDepth = namespacesSuspect.DepthOfIsUsedBy(suspect)
- // Select namespaces that are both using and used by namespaceSuspect
- let usersAndUsed = from n in namespacesSuspect where
- namespacesUserDepth[n] > 0 &&
- namespacesUsedDepth[n] > 0
- select n
- where usersAndUsed.Count() > 0
- // Here we've found namespace(s) both using and used by the suspect namespace.
- // A cycle involving the suspect namespace is found!
- let cycle = usersAndUsed.Append(suspect)
- // Fill hashset with namespaces in the cycle.
- // .ToArray() is needed to force the iterating process.
- let unused1 = (from n in cycle let unused2 = hashset.Add(n) select n).ToArray()
- select new { suspect, cycle }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement