我在NDepend版本2018.1.1中尝试了此代码,并对堆栈溢出中发布的原始代码进行了一些更改。它是为了获得具有循环依赖关系的方法(即相互调用并形成循环/循环代码)
但是这个代码似乎不适用于最新的nDepend。
注意:与StackOverflow上的其他代码的唯一区别在于,根据版本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 }
答案 0 :(得分: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 = Application.Methods.Where(m => m.Level == null)
同样增加NDepend&gt;选项&gt; CQLinq查询执行超时到60秒,因为查询在大型代码库上运行速度很慢,且遍历所有图形。
请记住,循环不一定像A调用B调用C调用A那样简单。循环是一组方法,其中从任何方法,循环中的任何其他方法都有路径。它可能非常复杂,如:
要显示方法循环,只需将其导出到代码图:
通常要打破周期,首先要打破相互依赖关系,例如A调用B和B调用A。
方法循环不一定是代码气味,例如许多GoF设计模式依赖于方法循环。