8

현재 솔루션 내의 순환 참조를 확인하려면 Architecture - Generate Dependency Graph - For Solution을 선택하십시오. 그런 다음 열리는 새 탭에서 Layout - Analyzers - Circular References Analyzer을 선택합니다. 마지막으로 개별 어셈블리에서 드릴 다운하고 순환 참조가있는 경우 그래프에서 빨간색으로 강조 표시된 것을 볼 수 있으며 오류 목록에도 경고로 나타납니다.Visual Studio 2012 - 효율적으로 순환 참조 찾기

동일한 클래스의 메서드 사이에서도 순환 참조를 발견하려고하므로 이는 상당히 오류가 많고 적당히 큰 코드베이스에서 시간이 많이 걸립니다.

노드를 확장하지 않고 모든 경고를 한 번에 가져 오거나 상위 노드의 강조 표시를 켜지 않으면 원형에 확실히 포함 된 조립품 만 드릴 다운 할 수 있는지 알고 싶습니다. 참조.

NDepend는 도움이 될 수 있지만 가능한 한 간단하게 유지하는 것이 더 좋으므로 추가 도구를 채택 할 때는 항상주의해야합니다.

+0

순환 참조를 빠르게 찾을 수있는 관련 유틸리티 : http://stackoverflow.com/a/43374622/64334 –

답변

6

예 NDepend가 효율적으로 날 당신이 생각하는 것보다 쉬울 수 있기 때문에 방법을 설명하자 순환 참조 찾을 수 있습니다 (면책 조항 : 나는 NDepend에 대한 개발자의 일 오전). 지금까지 당신은 찾을 수 네임 스페이스 의존성주기 아웃 - 오브 - 박스 내가 아래에 설명하고, 네임 스페이스에 유형, 또는 방법 (A)의 사이뿐만 아니라 사이클을 쉽게 찾을 수하지만, 유형.

네임 스페이스 종속성주기를 나열하는 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과 같은 대규모 코드 기반에서 실행될 때 10 초가 걸렸으며 (네임 스페이스주기의 경우 16ms 대신)이 조정을 조정해야 할 수도 있습니다 CQLinq 쿼리 실행 시간 제한 (기본값 당 2 초).

types dependency cycles

완료하기 위해, 내가 무엇을 발견하면 해당주기가 몇 양방향 참조에 의해 유발 대부분의 시간을하는 것입니다 (즉 A, B가 사용하고 B를 사용하고 있습니다). 따라서 양방향 참조를 제거하는 것이 순환을 중단시키는 첫 번째 방법입니다. 그렇기 때문에 우리는 기본 CQLinq 규칙 Avoid namespaces mutually dependent을 제공 했으므로 형식이나 메서드주기에 계속 적용 할 수 있습니다.