방법: 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 모델에 대한 유효성 검사 제약 조건 정의