Share via


레이어 다이어그램에 사용자 지정 아키텍처 유효성 검사 추가

업데이트: 2010년 12월

Visual Studio 2010 Ultimate 및 Visual Studio 2010 Premium에서 사용자는 Visual Studio 프로젝트의 소스 코드 유효성을 레이어 모델에 대해 검사하여 소스 코드가 레이어 다이어그램의 종속성을 따르는지 확인할 수 있습니다. 표준 유효성 검사 알고리즘이 있지만 이 Visual Studio 2010 Feature Pack을 사용하면 Visual Studio Ultimate 및 Visual Studio Premium용 유효성 검사 확장을 직접 정의할 수 있습니다. 자세한 내용은 Visual Studio 기능 팩을 참조하십시오.

사용자가 레이어 다이어그램에서 아키텍처 유효성 검사 명령을 선택하면 표준 유효성 검사 메서드가 호출되고 설치된 모든 유효성 검사 확장이 호출됩니다.

참고

레이어 다이어그램의 유효성 검사는 UML 다이어그램의 유효성 검사와 같지 않습니다. 레이어 다이어그램은 다이어그램을 솔루션의 다른 부분에 있는 프로그램 코드와 비교하는 데 주로 사용됩니다.

레이어 유효성 검사 확장을 VSIX(Visual Studio Integration Extension)로 패키지하여 다른 Visual Studio Ultimate 사용자에게 배포할 수 있습니다. VSIX에 유효성 검사기를 단독으로 배치하거나 다른 확장과 같은 VSIX에 유효성 검사기를 결합할 수 있습니다. 다른 확장과 같은 프로젝트가 아닌 고유한 Visual Studio 프로젝트에서 유효성 검사기 코드를 작성해야 합니다.

요구 사항

요구 사항 및 설치 지침은 레이어 다이어그램의 확장 만들기요구 사항을 참조하십시오.

새 VSIX에서 레이어 유효성 검사기 정의

유효성 검사기를 만드는 가장 빠른 방법은 프로젝트 템플릿을 사용하는 것입니다. 이 방법을 사용하는 경우 코드와 VSIX 매니페스트가 동일한 프로젝트에 배치됩니다.

프로젝트 템플릿을 사용하여 확장을 정의하려면

  1. 파일 메뉴에서 새 프로젝트 명령을 사용하여 새 솔루션에서 프로젝트를 만듭니다.

  2. 새 프로젝트 대화 상자의 모델링 프로젝트에서 Layer Designer Validation Extension(레이어 디자이너 유효성 검사 확장)을 선택합니다.

    템플릿은 작은 예가 포함된 프로젝트를 만듭니다.

  3. 코드를 편집하여 유효성 검사를 정의합니다. 자세한 내용은 유효성 검사 프로그래밍을 참조하십시오.

  4. 확장을 테스트하려면 레이어 유효성 검사 디버깅을 참조하십시오.

    참고

    메서드는 특정 상황에서만 호출되며 중단점은 자동으로 작동하지 않습니다. 자세한 내용은 레이어 유효성 검사 디버깅을 참조하십시오.

  5. Visual Studio의 주 인스턴스 또는 다른 컴퓨터에 확장을 설치하려면 **bin\***에서 .vsix 파일을 찾습니다. 이 파일을 설치할 컴퓨터에 복사한 다음 두 번 클릭합니다. 이 파일을 제거하려면 도구 메뉴에서 확장 관리자를 사용합니다.

별도의 VSIX에 레이어 유효성 검사기 추가

레이어 유효성 검사기, 명령 및 다른 확장이 포함된 VSIX를 만들려면 VSIX를 정의하기 위해 프로젝트를 만들고 처리기를 위해 별도의 프로젝트를 만드는 것이 좋습니다. 다른 유형의 모델링 확장에 대한 자세한 내용은 UML 모델 및 다이어그램 확장을 참조하십시오.

별도의 VSIX에 레이어 유효성 검사를 추가하려면

  1. 새 Visual Studio Ultimate 솔루션 또는 기존 솔루션에 클래스 라이브러리 프로젝트를 만듭니다. 새 프로젝트 대화 상자에서 **Visual C#**을 클릭한 다음 클래스 라이브러리를 클릭합니다. 이 프로젝트에는 레이어 유효성 검사 클래스가 포함됩니다.

  2. 솔루션에서 VSIX 프로젝트를 식별하거나 만듭니다. VSIX 프로젝트에는 source.extension.vsixmanifest라는 파일이 포함됩니다. VSIX 프로젝트를 추가해야 하는 경우 다음 단계를 수행합니다.

    1. 새 프로젝트 대화 상자에서 **Visual C#**을 확장하고 확장성을 클릭한 다음 VSIX 프로젝트를 클릭합니다.

    2. 솔루션 탐색기에서 VSIX 프로젝트를 마우스 오른쪽 단추로 클릭하고 시작 프로젝트로 설정을 클릭합니다.

    3. Select Editions(버전 선택)를 클릭하고 Visual Studio Ultimate가 선택되어 있는지 확인합니다.

  3. source.extension.vsixmanifest콘텐츠에서 레이어 유효성 검사 프로젝트를 MEF 구성 요소로 추가합니다.

    1. 콘텐츠 추가를 클릭합니다.

    2. 콘텐츠 형식 선택에서 MEF 구성 요소를 선택합니다.

    3. Select a source(소스 선택)에서 프로젝트를 클릭하고 명령 또는 제스처 처리기 프로젝트의 이름을 선택합니다.

    4. 파일을 저장합니다.

  4. 레이어 유효성 검사 프로젝트를 사용자 지정 확장으로 추가합니다.

    1. 콘텐츠 추가를 클릭합니다.

    2. 콘텐츠 형식 선택에서 사용자 지정 확장 형식을 선택합니다.

    3. 형식에서 Microsoft.VisualStudio.ArchitectureTools.Layer.Validator를 입력합니다.

    4. Select a source(소스 선택)에서 프로젝트를 클릭하고 유효성 검사 클래스 라이브러리 프로젝트의 이름을 선택합니다.

  5. 참조에서 참조 추가를 클릭하고 이 기능 팩의 런타임을 선택합니다.

  6. 레이어 유효성 검사 프로젝트로 돌아가서 다음 프로젝트 참조를 추가합니다.

    참조

    수행할 수 있는 작업

    Visual Studio 2010 Visualization and Modeling Feature Pack을 설치한 경우:

    %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions\Microsoft\Visualization and Modeling Feature Pack Runtime\1.0\Microsoft.VisualStudio.GraphModel.dll

    Visual Studio 2010 Feature Pack 2를 설치한 경우:

    …\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Visualization and Modeling Feature Pack Runtime\1.0\Microsoft.VisualStudio.GraphModel.dll

    아키텍처 그래프 읽기

    Visual Studio 2010 Visualization and Modeling Feature Pack을 설치한 경우:

    %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions\Microsoft\Visualization and Modeling Feature Pack Runtime\1.0\Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema.dll

    Visual Studio 2010 Feature Pack 2를 설치한 경우:

    …\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\ Visualization and Modeling Feature Pack Runtime\1.0\Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema.dll

    레이어와 연결된 코드 DOM 읽기

    Visual Studio 2010 Visualization and Modeling Feature Pack을 설치한 경우:

    %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions\Microsoft\Visualization and Modeling Feature Pack Runtime\1.0\Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer.dll

    Visual Studio 2010 Feature Pack 2를 설치한 경우:

    …\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Visualization and Modeling Feature Pack Runtime\1.0\Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer.dll

    레이어 모델 읽기

    Microsoft.VisualStudio.Uml.Interfaces

    레이어 모델 읽기

    Microsoft.VisualStudio.ArchitectureTools.Extensibility

    모양과 다이어그램 읽기 및 업데이트

    System.ComponentModel.Composition

    MEF(Managed Extensibility Framework)를 사용하여 유효성 검사 구성 요소 정의

    Microsoft.VisualStudio.Modeling.Sdk.10.0

    모델링 확장 정의

    참고

    %LocalAppData%는 일반적으로 DriveName:\Users\UserName\AppData\Local입니다. Windows XP 또는 Windows 2003에서는 %LocalAppData% 대신 %AppData%를 사용합니다.

  7. C# 클래스 라이브러리 프로젝트에서 클래스 파일을 편집하여 유효성 검사에 대한 코드를 포함합니다. 자세한 내용은 유효성 검사 프로그래밍을 참조하십시오.

  8. 확장을 테스트하려면 레이어 유효성 검사 디버깅을 참조하십시오.

    참고

    메서드는 특정 상황에서만 호출되며 중단점은 자동으로 작동하지 않습니다. 자세한 내용은 레이어 유효성 검사 디버깅을 참조하십시오.

  9. Visual Studio의 주 인스턴스 또는 다른 컴퓨터에 VSIX를 설치하려면 VSIX 프로젝트의 bin 디렉터리에서 .vsix 파일을 찾습니다. VSIX를 설치할 컴퓨터에 이 파일을 복사합니다. Windows 탐색기에서 VSIX 파일을 두 번 클릭합니다.

    이 파일을 제거하려면 도구 메뉴에서 확장 관리자를 사용합니다.

유효성 검사 프로그래밍

레이어 유효성 검사 확장을 정의하려면 다음 특징이 있는 클래스를 정의합니다.

  • 선언의 전체적인 형식은 다음과 같습니다.

      [Export(typeof(IValidateArchitectureExtension))]
      public partial class Validator1Extension :
                      IValidateArchitectureExtension
      {
        public void ValidateArchitecture(Graph graph)
        {
          var typeCategory = graph.DocumentSchema
                     .Categories.Get("CodeSchema_Type");
          var allTypes = graph.Nodes.GetByCategory(typeCategory);
        ...
          this.LogValidationError(graph, "SampleErrorId", 
             "Sample Validation Error", GraphErrorLevel.Error, allTypes);
        }
    
  • 오류를 발견하면 LogValidationError()를 사용하여 오류를 보고할 수 있습니다.

사용자가 아키텍처 유효성 검사 메뉴 명령을 호출하면 레이어 런타임 시스템에서 레이어와 해당 아티팩트를 분석하여 그래프를 생성합니다. 그래프는 네 부분으로 이루어져 있습니다.

  • 그래프에서 노드와 링크로 표현되는 Visual Studio 솔루션의 레이어 모델

  • 솔루션에 정의되고 노드로 표현되는 코드, 프로젝트 항목 및 기타 아티팩트와 분석 프로세스에서 검색되는 종속성을 나타내는 링크

  • 레이어 노드에서 코드 아티팩트 노드에 연결되는 링크

  • 유효성 검사기로 검색된 오류를 나타내는 노드

그래프가 생성되면 표준 유효성 검사 메서드가 호출됩니다. 이 작업이 완료되면 모든 설치된 확장 유효성 검사 메서드가 지정되지 않은 순서로 호출됩니다. 그래프가 각 ValidateArchitecture 메서드에 전달됩니다. 이 메서드는 그래프를 검사하고 발견한 모든 오류를 보고할 수 있습니다.

참고

이는 UML 다이어그램에 적용되는 유효성 검사 프로세스와 동일하지 않으며 도메인별 언어에서 사용할 수 있는 유효성 검사 프로세스와 동일하지 않습니다.

유효성 검사 메서드는 유효성이 검사되고 있는 레이어 모델이나 코드를 변경하지 않아야 합니다.

그래프 모델은 Microsoft.VisualStudio.GraphModel에 정의됩니다. 그래프 모델의 principal 클래스는 Node 및 Link입니다.

각 노드와 각 링크에는 해당 노드나 링크가 나타내는 요소 또는 관계의 형식을 지정하는 하나 이상의 범주가 있습니다. 일반적인 그래프의 노드에는 다음과 같은 범주가 있습니다.

  • Dsl.LayerModel

  • Dsl.Layer

  • Dsl.Reference

  • CodeSchema_Type

  • CodeSchema_Namespace

  • CodeSchema_Type

  • CodeSchema_Method

  • CodeSchema_Field

  • CodeSchema_Property

코드의 레이어에서 요소에 연결되는 링크에는 "Represents" 범주가 있습니다.

다음 코드는 아키텍처 유효성 검사 확장의 일반적인 예입니다. 이 코드에서는 솔루션의 코드에서 선언된 모든 형식이 레이어 모델에서 한 번 이상 참조되는지 확인합니다. 사용자는 모델의 부울 사용자 지정 속성을 설정하여 이 유효성 검사를 각 레이어 모델에 대해 수행해야 하는지 여부를 제어할 수 있습니다.

오류가 있으면 LogValidationError가 호출됩니다.

유효성 검사 디버깅

레이어 유효성 검사 확장을 디버깅하려면 Ctrl+F5를 누릅니다. 실험적 Visual Studio 인스턴스가 열립니다. 이 인스턴스에서 레이어 모델을 열거나 만듭니다. 이 모델은 코드와 연결되어야 하며 하나 이상의 종속성이 있어야 합니다.

종속성이 포함된 솔루션으로 테스트

다음 특징이 없는 경우 유효성 검사가 실행되지 않습니다.

  • 레이어 다이어그램에 종속성 링크가 하나 이상 있습니다.

  • 코드 요소와 연결된 레이어가 모델에 있습니다.

실험적 Visual Studio 인스턴스를 시작하여 유효성 검사 확장을 처음 테스트할 때 이러한 특징이 있는 솔루션을 열거나 만듭니다.

아키텍처 유효성 검사 전에 솔루션 정리 실행

유효성 검사 코드를 업데이트할 때마다 유효성 검사 명령을 테스트하기 전에 실험적 솔루션의 빌드 메뉴에서 솔루션 정리 명령을 사용합니다. 이는 유효성 검사의 결과가 캐시되기 때문에 필요합니다. 테스트 레이어 다이어그램이나 해당 코드를 업데이트하지 않은 경우 유효성 검사 메서드가 실행되지 않습니다.

명시적으로 디버거 시작

유효성 검사는 별도의 프로세스에서 실행됩니다. 따라서 유효성 검사 메서드의 중단점이 트리거되지 않습니다. 유효성 검사가 시작될 때 디버거를 프로세스에 명시적으로 연결해야 합니다.

디버거를 유효성 검사 프로세스에 연결하려면 유효성 검사 메서드의 시작 부분에 System.Diagnostics.Debugger.Launch() 호출을 삽입합니다. 디버깅 대화 상자가 나타나면 Visual Studio의 주 인스턴스를 선택합니다.

또는 System.Windows.Forms.MessageBox.Show() 호출을 삽입할 수 있습니다. 메시지 상자가 나타나면 Visual Studio의 주 인스턴스로 이동하고 디버그 메뉴에서 프로세스에 연결을 클릭합니다. Graphcmd.exe라는 프로세스를 선택합니다.

항상 Ctrl+F5(디버깅하지 않고 시작)를 눌러 실험적 인스턴스를 시작합니다.

유효성 검사 확장 배포

Visual Studio Ultimate 또는 Visual Studio Premium이 설치된 컴퓨터에 유효성 검사 확장을 설치하려면 대상 컴퓨터에서 VSIX 파일을 엽니다. Team Foundation Build가 설치된 컴퓨터에 설치하려면 VSIX 콘텐츠를 Extensions 폴더에 수동으로 추출해야 합니다. 자세한 내용은 레이어 모델링 확장 배포를 참조하십시오.

예제

다음 예에서는 레이어 유효성 검사 확장을 보여 줍니다.

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema;

using Microsoft.VisualStudio.GraphModel;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer;

namespace MyValidationExtensions
{ // This attribute identifies a layer validator:
  [Export(typeof(IValidateArchitectureExtension))]
  public partial class UnreferencedTypeValidatorExtension 
      : IValidateArchitectureExtension
  {
    private GraphCategory typeCategory = null;
    /// <summary>
    /// Validate the architecture
    /// </summary>
    /// <param name="graph">The graph</param>
    public void ValidateArchitecture(Graph graph)
    {
      // A good place to attach a debugger
      // System.Windows.Forms.MessageBox.Show("Attach - Unreferenced Type Validator");
      // To find the nodes that represent the code and the layers,
      // we need to filter by category.
      // Categories are identified by specific strings:
      if (typeCategory == null)
      {
        typeCategory = 
          graph.DocumentSchema.Categories.Get("CodeSchema_Type");
      }
      var layerModelCategory = 
        graph.DocumentSchema.Categories.Get("Dsl.LayerModel");
      var allLayerModels =
        graph.Nodes.GetByCategory(layerModelCategory);

      foreach (var layerModel in allLayerModels)
      {
        var allTypesMustBeReferencedProperty =
           ExtractProperty(layerModel, 
            AllTypesMustBeReferencedProperty.FullName);
        bool shouldAllTypesBeReferenced = 
          allTypesMustBeReferencedProperty == null 
          ? false 
          : Convert.ToBoolean(allTypesMustBeReferencedProperty);

        if (shouldAllTypesBeReferenced)
        {
          // Find all types referenced by layers:
          var referencedTypes = new HashSet<Node>();
          GetReferencedTypes(referencedTypes, layerModel);
          var allTypes = graph.Nodes.GetByCategory(typeCategory);

          foreach (var type in allTypes)
          {
            if (!referencedTypes.Contains(type))
            {
              // Filter out types that are not part of any 
              // assembly (for example referenced external types).
              if (type.GetContainmentSources(graph)
                .Where(n => n.HasCategory(graph.DocumentSchema
                .Categories.Get("CodeSchema_Assembly"))).Any())
              {
                // type is not referenced in the layer diagram
                this.LogValidationError(graph,
                    string.Format("{0}_UnreferencedTypeError_{1}",
                    GetFullyQualifiedTypeName(type), Guid.NewGuid()),
                    string.Format("AV1002 : Unreferenced type :"
                      + " {0}{2}Layer Diagram: {1}.layerdiagram.",
                        GetFullyQualifiedTypeName(type),
                        layerModel.Label,
                        Environment.NewLine),
                    GraphErrorLevel.Error,
                    new Node[] { type });
              }
            }
          }
        }
      }
    }

    private void GetReferencedTypes(HashSet<Node> referencedTypes, Node node)
    {
      foreach (Node containedNode in node.GetContainmentTargets(node.Owner))
      {
        if (referencedTypes.Contains(containedNode))
        {
          // We've seen this node before
          continue;
        }

        if (containedNode.HasCategory(typeCategory))
        {
          referencedTypes.Add(containedNode);
        }
        else
        {
          GetReferencedTypes(referencedTypes, containedNode);
        }
      }
    }
    public static string GetFullyQualifiedTypeName(Node typeNode)
    {
      try
      {
         string returnValue;
         CodeQualifiedIdentifierBuilder id = 
           new CodeQualifiedIdentifierBuilder(
                   typeNode.Id, typeNode.Owner);
         returnValue = id.GetFullyQualifiedLabel(
              CodeQualifiedIdentifierBuilder.LabelFormat
              .NoAssemblyPrefix);
        return returnValue;
      }
      catch { }
     return typeNode.Label;
  }

  public static object ExtractProperty
             (Node layerModel, string propertyName)
  {
    object propertyValue = null;
    var propertyCategory = 
        layerModel.Owner.DocumentSchema.GetProperty(propertyName);
    if (propertyCategory != null)
    {
      propertyValue = layerModel[propertyCategory];
    }
    return propertyValue;
  }
}

참고 항목

기타 리소스

레이어 다이어그램의 확장 만들기

변경 기록

날짜

변경 내용

이유

2010년 12월

Visual Studio 2010 Feature Pack 2에 대한 내용을 업데이트했습니다.

향상된 기능 관련 정보