방법: UML API를 사용하여 시퀀스 다이어그램 편집

상호 작용은 수명선 집합 간의 메시지 시퀀스이며 시퀀스 다이어그램에 표시됩니다.

API에 대한 자세한 내용은 Microsoft.VisualStudio.Uml.Interactions를 참조하십시오.

UML 다이어그램에 대한 명령 및 제스처 처리기를 작성하는 보다 일반적인 지침은 방법: 모델링 다이어그램의 메뉴 명령 정의를 참조하십시오.

기본 코드

네임스페이스 가져오기

다음과 같은 using 문을 포함해야 합니다.

using Microsoft.VisualStudio.Uml.Classes;
   // for basic UML types such as IPackage
using Microsoft.VisualStudio.Uml.Interactions;
   // for interaction types
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
   // to create elements and use additional functions

메뉴 명령 및 제스처 처리기를 만드는 경우 다음 코드도 필요합니다.

using System.ComponentModel.Composition; 
   // for Import and Export
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;
   // for ICommandExtension
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
   // for diagrams and context

자세한 내용은 방법: 모델링 다이어그램의 메뉴 명령 정의를 참조하십시오.

컨텍스트 가져오기

시퀀스 다이어그램에서 명령 또는 제스처 처리기의 일부로 상호 작용을 편집하는 경우 컨텍스트에 대한 참조를 가져올 수 있습니다. 예를 들면 다음과 같습니다.

    [SequenceDesignerExtension]
    [Export(typeof(ICommandExtension))]  
    public class MySequenceDiagramCommand : ICommandExtension
    {
        [Import]
        public IDiagramContext Context { get; set; }
        public void QueryStatus (IMenuCommand command)
        {
          ISequenceDiagram sequenceDiagram = 
              Context.CurrentDiagram as ISequenceDiagram;
             ...

생성된 시퀀스 다이어그램과 UML 시퀀스 다이어그램

시퀀스 다이어그램에는 UML 모델링 프로젝트에서 수동으로 만드는 다이어그램과 프로그램 코드에서 생성되는 다이어그램 등 두 가지 종류가 있습니다. UmlMode 속성을 사용하여 작업 중인 시퀀스 다이어그램의 종류를 찾을 수 있습니다.

예를 들어 UML 시퀀스 다이어그램에만 표시되는 메뉴 명령을 만들려는 경우 QueryStatus() 메서드에 다음 문을 포함할 수 있습니다.

    command.Enabled = command.Visible = 
          sequenceDiagram != null && sequenceDiagram.UmlMode;

생성된 시퀀스 다이어그램에서 수명선, 메시지 및 기타 요소는 UML 시퀀스 다이어그램의 해당 요소와 동일합니다. UML 모델에서 모델 저장소에는 다른 모든 요소를 소유하는 모델 루트가 있지만, 생성된 상호 작용은 null 루트가 있는 자체 모델 저장소에 존재합니다.

    IModel rootModel = sequenceDiagram.ModelStore.Root;
    // !sequenceDiagram.UmlMode == (rootModel == null)

상호 작용을 만들고 표시하려면

상호 작용을 패키지 또는 모델의 자식으로 만듭니다.

예를 들어 빈 시퀀스 다이어그램에 대해 수행할 수 있는 명령을 개발하는 경우에는 항상 상호 작용이 있는지 여부부터 확인해야 합니다.

public void Execute (IMenuCommand command)
{
    ISequenceDiagram sequenceDiagram = 
         Context.CurrentDiagram as ISequenceDiagram;
    if (sequenceDiagram == null) return;
    // Get the diagram's interaction:
    IInteraction interaction = sequenceDiagram.Interaction;
    // A new sequence diagram might have no interaction:
    if (interaction == null)
    {
       // Get the home package or model of the diagram:
       IPackage parentPackage = sequenceDiagram.GetObject<IPackage>();
       interaction = parentPackage.CreateInteraction();
       // Display the interaction on the sequence diagram:
       sequenceDiagram.Bind(interaction);
    } 

상호 작용 및 해당 레이아웃 업데이트

상호 작용을 업데이트할 때는 항상 다음 메서드 중 하나를 사용하여 해당 레이아웃을 업데이트하는 것으로 작업을 마쳐야 합니다.

  • ISequenceDiagram.UpdateShapePositions() - 최근에 삽입 또는 이동된 모양과 인접 모양의 위치를 조정합니다.

  • ISequenceDiagram.Layout([SequenceDiagramLayoutKinds]) - 전체 다이어그램을 다시 그립니다. 매개 변수를 사용하여 수명선, 메시지 또는 둘 모두의 변경할 위치를 지정할 수 있습니다.

이 작업은 새 요소를 삽입하거나 기존 요소를 이동한 경우에 특히 중요합니다. 이러한 작업 중 하나를 수행하기 전까지는 삽입 또는 이동된 요소가 다이어그램에서 올바른 위치에 배치되지 않습니다. 일련의 변경 작업을 끝낸 후 이러한 작업 중 하나를 한 번만 호출하면 됩니다.

명령을 실행한 후 취소하는 사용자에게 혼란을 주지 않으려면 ILinkedUndoTransaction을 사용하여 변경 내용과 최종 Layout() 또는 UpdateShapePositions() 작업을 포함합니다. 예를 들면 다음과 같습니다.

using (ILinkedUndoTransaction transaction = LinkedUndoContext.BeginTransaction("create loop"))
{
  Interaction.CreateCombinedFragment(InteractionOperatorKind.Loop, messages);
  Diagram.UpdateShapePositions();
  transaction.Commit();
}

ILinkedUndoTransaction을 사용하려면 클래스에서 다음과 같이 선언해야 합니다.

[Import] ILinkedUndoContext LinkedUndoContext { get; set; }

자세한 내용은 방법: 트랜잭션을 사용하여 모델 업데이트 연결을 참조하십시오.

상호 작용 빌드

수명선을 만들려면

ILifeline lifeline = interaction.CreateLifeline();

수명선은 연결 가능 요소, 즉 형식의 인스턴스를 나타냅니다. 예를 들어 구성 요소가 들어오는 메시지를 내부 파트에 위임하는 방식을 나타내기 위해 상호 작용을 사용하는 경우 수명선은 구성 요소의 포트 및 파트를 나타낼 수 있습니다.

foreach (IConnectableElement part in 
            component.Parts
           .Concat<IConnectableElement>(component.OwnedPorts))
{
   ILifeline lifeline = interaction.CreateLifeline();
   lifeline.Represents = part;
}

상호 작용에서 임의의 개체 집합을 나타내는 경우에는 다음과 같이 상호 작용 자체에 속성 또는 다른 IConnectableElement를 만들 수도 있습니다.

ILifeline lifeline = interaction.CreateLifeline();
IProperty property1 = interaction.CreateProperty();
property1.Type = model.CreateInterface();
property1.Type.Name = "Type 1";
lifeline.Represents = property1;

또 다른 방법으로, 다음과 같이 수명선을 연결 가능 요소에 연결하지 않고 수명선의 이름과 형식을 설정할 수 있습니다.

ILifeline lifeline = interaction.CreateLifeline();
lifeline.Name = "c1";
lifeline.SetInstanceType("Customer");
System.Diagnostics.Debug.Assert(
           lifeline.GetDisplayName() == "c1:Customer"  );

메시지를 만들려면

메시지를 만들려면 소스 및 대상 수명선에서 삽입 지점을 식별해야 합니다. 예를 들면 다음과 같습니다.

interaction.CreateMessage( sourceInsertionPoint, 
                           targetInsertionPoint, 
                           MessageKind.Complete, 
                           MessageSort.ASynchCall)

소스 또는 대상이 정의되지 않은 메시지를 만들려면 다음과 같이 합니다.

interaction.CreateLostFoundMessage(MessageKind.Found, insertionPoint);

수명선의 모든 주요 지점에서 삽입 지점을 식별하는 데 사용할 수 있는 몇 가지 메시지가 있습니다.

ILifeline의 메서드

삽입 지점

FindInsertionPointAtTop()

수명선의 맨 위

FindInsertionPointAtBottom()

수명선의 맨 아래

FindInsertionPointAfterMessage

(IMessage previous)

지정된 메시지 바로 다음의 지점

FindInsertionPointAfterExecutionSpecification

(IExecutionSpecification previous)

수명선 또는 부모 실행 사양 블록의 한 지점이 될 수 있습니다.

FindInsertionPointAfterInteractionUse

(IInteractionUse previous)

상호 작용 사용 다음의 지점

FindInsertionPointAfterCombinedFragment

(ICombinedFragment previous)

결합 조각 다음의 지점

FindInsertionPoint(IExecutionSpecification block)

실행 블록의 맨 위

FindInsertionPoint(IInteractionOperand fragment)

결합 조각의 피연산자 맨 위

메시지를 만들 때는 다른 메시지와 교차하는 메시지를 정의하지 않도록 주의해야 합니다.

결합 조각 및 상호 작용 사용을 만들려면

요소가 나타내야 하는 각 수명선에 삽입 지점을 지정하여 결합 조각 및 상호 작용 사용을 만들 수 있습니다. 이때 기존 메시지 또는 조각과 교차하는 일련의 지점을 지정하지 않도록 주의해야 합니다.

Interaction.CreateCombinedFragment(InteractionOperatorKind.Loop, 
  Interaction.Lifelines.Select(lifeline => lifeline.FindInsertionPointAtTop()));
Interaction.CreateInteractionUse(
  Interaction.Lifelines.Select(lifeline => lifeline.FindInsertionPointAtTop()));

기존 메시지 집합을 나타내는 결합 조각을 만들 수도 있습니다. 해당 메시지는 모두 동일한 수명선 또는 실행 블록에서 발생해야 합니다.

ICombinedFragment cf = Interaction.CreateCombinedFragment(
  InteractionOperatorKind.Loop,
  Interaction.Lifelines.First().GetAllOutgoingMessages());

결합 조각은 항상 단일 피연산자를 사용하여 만들어집니다. 새 피연산자를 만들려면 삽입할 피연산자의 앞 또는 뒤에 있는 기존 피연산자를 지정하고 새 연산자를 이 앞에 삽입할지 뒤에 삽입할지를 지정해야 합니다.

// Create an additional operand before the first
cf.CreateInteractionOperand(cf.Operands.First(), false);
// Create an additional operand after the last:
cf.CreateInteractionOperand(cf.Operands.Last(), true);

문제 해결

변경 작업이 UpdateShapePositions() 또는 Layout() 작업으로 완료되지 않은 경우에는 모양이 올바르지 않은 위치에 나타납니다.

그 외의 문제는 대부분 삽입 지점의 위치가 잘못되어 새 메시지 또는 조각이 다른 메시지 또는 조각과 교차하게 될 경우에 발생합니다. 이 경우 변경 작업이 수행되지 않거나 예외가 throw되는 증상이 있을 수 있습니다. UpdateShapePositions() 또는 Layout() 작업이 수행되기 전까지는 예외가 throw되지 않을 수도 있습니다.

참고 항목

참조

Microsoft.VisualStudio.Uml.Interactions

개념

UML 모델 및 다이어그램 확장

방법: 모델링 다이어그램의 메뉴 명령 정의

방법: 사용자 지정 모델링 도구 상자 항목 정의

방법: UML 모델에 대한 유효성 검사 제약 조건 정의

UML API를 사용한 프로그래밍