C# Как получить Циркулярные методы в проекте / решении с помощью ndepend в последней версии 2018.1.1
Я попробовал этот код в версии 2018.1.1 NDepend с некоторыми изменениями, внесенными в исходный код, который был размещен в stackru. Это чтобы получить методы, которые имеют циклические зависимости (то есть вызывать друг друга и формировать циклический / циклический код)
Но этот Код, похоже, не работает в последней версии nDepend.
Примечание: единственное отличие от другого кода в Stackru заключается в том, что этот код соответствует требованиям версии 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 }
1 ответ
Предоставленный запрос отлично работает с моей стороны, чтобы найти циклы методов внутри типа.
Для общего цикла методов (независимо от их родительского типа) просто измените начало запроса таким образом.
//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 > Options > CQLinq до 60 секунд, потому что запрос может быть медленным на большой базе кода со всем обходом графа.
Имейте в виду, что цикл не обязательно так прост, как вызовы A, вызовы B, вызовы C, вызовы A. Цикл - это набор методов, в котором из любого метода есть путь к любому другому методу в цикле. Это может быть довольно сложно, как:
Чтобы визуализировать цикл метода, просто экспортируйте его в граф кода:
Как правило, чтобы разорвать циклы, начните с разрыва взаимозависимостей, как A вызывает B и B вызывает A.
Цикл метода не обязательно является запахом кода, многие шаблоны проектирования GoF, например, полагаются на цикл метода.