Rob*_*van 8 .net circular-dependency circular-reference visual-studio visual-studio-2012
目前,如果我想在我选择的解决方案中检查循环引用Architecture - Generate Dependency Graph - For Solution.然后从我打开的新选项卡中选择Layout - Analyzers - Circular References Analyzer.最后,如果我从单个程序集向下钻取并且有循环引用,我可以在图表上看到它们以红色突出显示,它们也在错误列表中显示为警告.
由于我打算在相同类的方法之间发现循环引用,因此在适度大的代码库上这非常容易出错且耗时.
我想知道是否有一种方法可以立即获取所有警告,而无需扩展节点或者可能打开父节点的突出显示,这样我就可以只查看肯定包含循环引用的汇编.
NDepend应该能够提供帮助,但我更喜欢让事情变得尽可能简单,所以我总是对采用其他工具持谨慎态度.
是的NDepend可以找到循环引用有效地让我解释一下因为它可能比你想象的更容易(免责声明:我是NDepend的开发人员之一).到目前为止,你可以找到开箱即用的命名空间依赖循环,但正如我在下面解释的那样,很容易找到命名空间中类型之间的循环或类型的方法.
有一个默认的C#LINQ代码规则列出了名称空间依赖循环.然后可以将这种循环导出到依赖图或依赖矩阵.以下是2012年6月Roslyn代码库CTP上执行的规则的屏幕截图(注意它只需要16毫秒才能运行).它找到了11个不同的周期,如屏幕截图所示,您可以深入查看每个周期并将周期导出到图表中:

这是7名称空间循环的依赖关系图.请注意,它看起来比传统的O形环循环更复杂.这里的关键是,从这些命名空间中的任何一个,您都可以访问所有其他命名空间.这是循环(纠缠)的概括概念.

列出命名空间依赖性循环的默认C#LINQ代码规则的代码乍一看可能看起来令人生畏.但是C#开发人员应该在几分钟内理解它,然后可以轻松地调整它以找到任何类型的依赖循环.
例如,要查找相同类型循环的方法(而不是相同程序集循环的名称空间),它几乎就像通过方法替换所有名称空间字一样简单,并按类型汇编单词.
// <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 = usersAndUsed.Append(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 }
Run Code Online (Sandbox Code Playgroud)
...以下是此规则的结果如何(仍然可以将方法循环导出到依赖关系图或矩阵).请注意,由于方法和类型的数量远远高于命名空间和程序集的数量,因此此查询在Roslyn等大型代码库上运行需要10秒钟(而不是16ms用于命名空间循环),因此您可能需要调整CQLinq查询执行超时(默认为2秒).

为了完整,我注意到循环是大部分时间由一些双向参考引起的(即A使用B,B使用A).因此,删除双向引用是打破循环的第一步.这就是我们提供默认CQLinq规则避免名称空间相互依赖的原因,它仍然可以适应类型或方法周期.
| 归档时间: |
|
| 查看次数: |
6451 次 |
| 最近记录: |