C# 如何在最新版本 2018.1.1 中使用 ndepend 获取 Project/Solution 中的循环方法

C# How to get the Circular Methods in a Project/Solution using ndepend in the latest version 2018.1.1

我在 NDepend 版本 2018.1.1 中尝试了此代码,并对发布在 Whosebug 上的原始代码进行了一些更改。就是获取循环依赖的Methods(即相互调用,形成cyclic/circular代码)

但是这段代码在最新的nDepend中似乎不起作用。

注意:与 Whosebug 上的其他代码唯一不同的是,根据版本 2018.1.1 的要求,此代码具有此功能;

let cycle = ExtensionMethodsEnumerable.Append(usersAndUsed,suspect)

代码......

    // <Name>Avoid methods of a type to be in cycles</Name>
warnif count > 0


from t in Application.Types
                 .Where(t => t.ContainsMethodDependencyCycle != null && 
                             t.ContainsMethodDependencyCycle.Value)

// Optimization: restreint methods set
// A method involved in a cycle necessarily have a null Level.
let methodsSuspect = t.Methods.Where(m => m.Level == null)

// hashset is used to avoid iterating again on methods already caught in a cycle.
let hashset = new HashSet<IMethod>()


from suspect in methodsSuspect
   // By commenting this line, the query matches all methods involved in a cycle.
   where !hashset.Contains(suspect)

   // Define 2 code metrics
   // - Methods depth of is using indirectly the suspect method.
   // - Methods depth of is used by the suspect method indirectly.
   // Note: for direct usage the depth is equal to 1.
   let methodsUserDepth = methodsSuspect.DepthOfIsUsing(suspect)
   let methodsUsedDepth = methodsSuspect.DepthOfIsUsedBy(suspect)

   // Select methods that are both using and used by methodSuspect
   let usersAndUsed = from n in methodsSuspect where
                         methodsUserDepth[n] > 0 && 
                         methodsUsedDepth[n] > 0 
                      select n

   where usersAndUsed.Count() > 0

   // Here we've found method(s) both using and used by the suspect method.
   // A cycle involving the suspect method is found!
   let cycle = ExtensionMethodsEnumerable.Append(usersAndUsed,suspect)

   // Fill hashset with methods 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 }

提供的查询在我这边工作正常,可以在一个类型中找到方法循环。

对于一般循环的方法(无论它们的父类型如何)只需以这种方式修改查询的开头。

//from t in Application.Types
//                 .Where(t => t.ContainsMethodDependencyCycle != null && 
//                             t.ContainsMethodDependencyCycle.Value)

// Optimization: restreint methods set
// A method involved in a cycle necessarily have a null Level.
let methodsSuspect = Application.Methods.Where(m => m.Level == null)

还将 NDepend > 选项 > CQLinq 查询执行超时增加到 60 秒,因为在具有所有图形遍历的大型代码库上查询可能会很慢。

请记住,循环并不一定像 A 调用 B 调用 C 调用 A 那样简单。循环是一组方法,其中从任何方法到循环中的任何其他方法都有路径。它可能非常复杂,例如:

要可视化方法循环,​​只需将其导出到代码图中:

通常要打破循环,首先要打破相互依赖,比如 A 调用 B,B 调用 A。

方法循环不一定是代码味道,例如许多 GoF 设计模式都依赖于方法循环。