HOW TO:使用 UML API 編輯順序圖表
互動是一組生命線之間的訊息系列。順序圖表上會顯示互動。
如需 API 的詳細資料,請參閱Microsoft.VisualStudio.Uml.Interactions。
如需為 UML 圖表撰寫命令和筆勢處理常式的一般介紹,請參閱 HOW TO:在模型圖表上定義功能表命令。
基本程式碼
命名空間匯入
您必須包含下列 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
如需詳細資訊,請參閱HOW TO:在模型圖表上定義功能表命令。
取得內容
如果您以順序圖表中命令或筆勢處理常式的一部分編輯互動,則可以取得以下內容的參考。例如:
[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; }
如需詳細資訊,請參閱HOW TO:使用交易連結模型更新。
建置互動
若要建立生命線
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);
您可以使用數則訊息來識別生命線上所有關鍵點的插入點:
生命線上的方法 |
使用該方法來在此點插入 |
---|---|
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() 作業完成變更,圖案將會出現在不正確的位置上。
其他的問題大多導因於插入點未對齊,而使新的訊息或片段必須跨界到其他訊息或片段上。若未執行任何變更,或有例外狀況擲回,表示可能有此狀況。在 UpdateShapePositions() 或 Layout() 作業執行前並不會擲回例外狀況。
請參閱
參考
Microsoft.VisualStudio.Uml.Interactions