8

現在、ソリューション内の循環参照をチェックする場合は、Architecture - Generate Dependency Graph - For Solutionを選択します。 新しいタブが開いたら、私はLayout - Analyzers - Circular References Analyzerを選択します。 最後に、個々のアセンブリからドリルダウンして循環参照がある場合、グラフ上で赤で強調表示され、エラーリストに警告として表示されます。Visual Studio 2012 - 循環参照を効率的に検索

同じクラスのメソッド間でも循環参照を見つけるつもりであるため、これは非常にエラーが発生しやすく、適度に大きなコードベースでは時間がかかります。

ノードを展開することなく一度にすべての警告を取得する方法があるか、親ノードの強調表示を有効にする方法があるかどうかを知りたいので、必ず円形を含むアセンブリのみをドリルダウンできます参照。

NDependが役立つはずですが、私は可能な限りシンプルなものを保つことを好むので、私は追加のツールを採用することに常に注意しています。

はいNDependのが効率的が、あなたが( 免責事項:私はNDependのの開発者の一人だ)と思うかもしれないより簡単であるかもしれないので、私はどのように説明させて循環参照を 見つけることができます
+0

循環参照を迅速に見つけるための関連ユーティリティ:http://stackoverflow.com/a/43374622/64334 –

答えて

6

。これまでのところ、あなたは見つけることができます名前空間依存サイクルすぐに私は、以下の説明していますように、名前空間の種類、または方法のの間、同様のサイクルを見つけることは容易である、しかし、タイプ。

名前空間依存サイクルをリストするdefault C# LINQ code ruleがあります。このようなサイクルは、従属グラフまたは依存行列にエクスポートできます。 RoslynコードベースCTP(2012年6月)で実行されたルールのスクリーンショットです(実行にはわずか16ミリ秒かかります)。これは、11回の異なるサイクルを発見し、スクリーンショットに示すように、あなたは、各サイクルにドリルダウンして、グラフにサイクルをエクスポートすることができます。ここでは

Rule to match namespace dependency cycle

が7つの名前空間サイクルの依存関係グラフです。古典的なOリングサイクルより複雑に見えることに注意してください。ここの鍵は、これらの名前空間のいずれかから、他のすべての名前空間に到達できることです。これはサイクル(エンタングルリング)の一般化された概念です。

Match namespace dependency cycle Graph

依存サイクルが一見困難な見えるかもしれません名前空間を一覧表示しますdefault C# LINQ code ruleのコード。しかし、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 } 

...と、ここでは、この規則の結果は(まだ依存関係グラフまたはマトリックスにメソッドサイクルをエクスポートする可能性を持つ)のように見える方法です。メソッドと型の数は名前空間やアセンブリの数よりはるかに多いので、このクエリはRoslyn(名前空間のサイクルでは16msではなく)のような大きなコードベースで実行するのに10秒かかりましたので、調整する必要があるかもしれませんCQLinqクエリ実行のタイムアウト(デフォルトあたり2秒)。

types dependency cycles

私が気づいたことは、そのサイクルで、完全であることを、いくつかの双方向参照によって誘発されるほとんどの時間です(すなわち、AがBを使用して、BはAを使用しています)。したがって、双方向参照を削除することは、サイクルを中断するために最初に行うことです。このため、デフォルトのCQLinqルールAvoid namespaces mutually dependentを提供しましたが、これは引き続きタイプまたはメソッドサイクルに適合させることができます。