Como: Editar diagramas de seqüência usando a API de UML
Uma interação é uma seqüência de mensagens entre um conjunto de linhas de vida.Uma interação é exibida em um diagrama de seqüência.
Para obter detalhes completos da API, consulte Microsoft.VisualStudio.Uml.Interactions.
Para obter uma introdução mais geral para escrever os comandos e manipuladores de gesto para diagramas UML, consulte Como: definir um comando de Menu em um diagrama de modelagem.
Código básico
Importações de namespace
Você deve incluir o seguinte using instruções:
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
Se você estiver criando comandos de menu e manipuladores de gesto, também será necessário:
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
Para obter mais informações, consulte Como: definir um comando de Menu em um diagrama de modelagem.
Obtendo o contexto
Se você estiver editando uma interação como parte de um manipulador de comando ou o gesto em um diagrama de seqüência, você pode obter uma referência ao contexto.Por exemplo:
[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;
...
Gerado e diagramas de seqüência UML
Existem dois tipos de diagramas de seqüência: aquelas criadas manualmente em um projeto de modelagem UML e aqueles que são gerados a partir do código de programa.Você pode usar o UmlMode propriedade para descobrir que tipo de diagrama de seqüência que você estiver trabalhando com.
Por exemplo, se você quiser fazer um comando de menu só é visível em diagramas de seqüência UML, em seguida, a QueryStatus() método poderia incluir a instrução a seguir:
command.Enabled = command.Visible =
sequenceDiagram != null && sequenceDiagram.UmlMode;
Em uma seqüência gerada, diagrama, as linhas de vida, mensagens e outros elementos são muito semelhante a como em um diagrama de seqüência UML.Em um modelo UML, o modelo de armazenamento tem uma raiz, que é o modelo que possui todos os outros elementos; mas uma interação gerada existe em seu próprio armazenamento de modelo, que tem uma raiz nula:
IModel rootModel = sequenceDiagram.ModelStore.Root;
// !sequenceDiagram.UmlMode == (rootModel == null)
Para criar e exibir uma interação
Crie a interação como um filho de um pacote ou um modelo.
Por exemplo, se você estiver desenvolvendo um comando que pode ser executado em um diagrama de seqüência em branco, você deve sempre começar, verificando se a interação existe.
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);
}
Atualizando uma interação e seu Layout
Quando você atualiza uma interação, sempre termine sua operação atualizando seu layout usando um dos seguintes métodos:
ISequenceDiagram.UpdateShapePositions() Ajusta as posições das formas que tenham sido recentemente inseridas ou movidas e seus vizinhos.
ISequenceDiagram.Layout([SequenceDiagramLayoutKinds])redesenha todo o diagrama.Você pode usar o parâmetro para especificar o reposicionamento das linhas de vida, as mensagens ou ambos.
Isso é particularmente importante quando você insere novos elementos ou move elementos existentes.Eles não serão nas posições corretas no diagrama até que você executou uma dessas operações.Você só precisará chamar uma dessas operações, uma vez no final de uma série de alterações.
Para evitar bemusing o usuário que executa um comando Desfazer após seu comando, use um ILinkedUndoTransaction para delimitar suas alterações e o final Layout() ou UpdateShapePositions() as operações.Por exemplo:
using (ILinkedUndoTransaction transaction = LinkedUndoContext.BeginTransaction("create loop"))
{
Interaction.CreateCombinedFragment(InteractionOperatorKind.Loop, messages);
Diagram.UpdateShapePositions();
transaction.Commit();
}
Para usar um ILinkedUndoTransaction, você deve fazer essa declaração na sua classe:
[Import] ILinkedUndoContext LinkedUndoContext { get; set; }
Para obter mais informações, consulte Como: atualizações do modelo de Link usando transações.
A criação de uma interação
Para criar linhas de vida
ILifeline lifeline = interaction.CreateLifeline();
Uma linha de vida representa um elemento conectável, ou seja, uma instância de um tipo.Por exemplo, se a interação é usada para mostrar como um componente delega as mensagens de entrada para as suas partes internas, as linhas de vida podem representar as portas e partes do componente:
foreach (IConnectableElement part in
component.Parts
.Concat<IConnectableElement>(component.OwnedPorts))
{
ILifeline lifeline = interaction.CreateLifeline();
lifeline.Represents = part;
}
Como alternativa, se a interação mostra um conjunto arbitrário de objetos, você pode criar uma propriedade ou outros IConnectableElement na interação propriamente dita:
ILifeline lifeline = interaction.CreateLifeline();
IProperty property1 = interaction.CreateProperty();
property1.Type = model.CreateInterface();
property1.Type.Name = "Type 1";
lifeline.Represents = property1;
Como outra alternativa, você pode definir o nome e o tipo de uma linha de vida sem vinculá-la a um elemento conectável:
ILifeline lifeline = interaction.CreateLifeline();
lifeline.Name = "c1";
lifeline.SetInstanceType("Customer");
System.Diagnostics.Debug.Assert(
lifeline.GetDisplayName() == "c1:Customer" );
Para criar mensagens
Para criar uma mensagem, você deve identificar os pontos de inserção sobre as linhas de vida de origem e de destino.Por exemplo:
interaction.CreateMessage( sourceInsertionPoint,
targetInsertionPoint,
MessageKind.Complete,
MessageSort.ASynchCall)
Para criar uma mensagem que tenha uma origem indefinida ou destino indefinido:
interaction.CreateLostFoundMessage(MessageKind.Found, insertionPoint);
Há a várias mensagens que você pode usar para identificar pontos de inserção em todos os principais pontos em uma linha de vida:
Método em ILifeline |
Usada para inserir neste momento |
---|---|
FindInsertionPointAtTop() |
Na parte superior da linha de vida. |
FindInsertionPointAtBottom() |
Na parte inferior da linha de vida. |
FindInsertionPointAfterMessage (IMessage previous) |
Um ponto imediatamente após a mensagem especificada. |
FindInsertionPointAfterExecutionSpecification (IExecutionSpecification previous) |
O ponto pode ser na linha de vida ou em um bloco de especificação de execução do pai. |
FindInsertionPointAfterInteractionUse (IInteractionUse previous) |
Um ponto após o uso de uma interação. |
FindInsertionPointAfterCombinedFragment (ICombinedFragment previous) |
Um ponto de um fragmento combinado a seguir. |
FindInsertionPoint(IExecutionSpecification block) |
Na parte superior de um bloco de execução. |
FindInsertionPoint(IInteractionOperand fragment) |
Na parte superior de um operando de um fragmento combinado. |
Quando você cria mensagens, tome cuidado para evitar a definição de uma mensagem que passa pela outra mensagem.
Para criar fragmentos combinados e interação usa
Você pode criar fragmentos combinados e interação usa especificando um ponto de inserção em cada linha de vida que deve ser coberta pelo elemento.Tome cuidado para evitar a especificação de um conjunto de pontos que passa através de uma mensagem existente ou um fragmento.
Interaction.CreateCombinedFragment(InteractionOperatorKind.Loop,
Interaction.Lifelines.Select(lifeline => lifeline.FindInsertionPointAtTop()));
Interaction.CreateInteractionUse(
Interaction.Lifelines.Select(lifeline => lifeline.FindInsertionPointAtTop()));
Você também pode criar um fragmento combinado que abrange um conjunto de mensagens existentes.Todas as mensagens devem ser originadas na mesma linha de vida ou bloco de execução.
ICombinedFragment cf = Interaction.CreateCombinedFragment(
InteractionOperatorKind.Loop,
Interaction.Lifelines.First().GetAllOutgoingMessages());
Um fragmento combinado é sempre criado com um único operando.Para criar um novo operando, você deve especificar o operando existente que você deseja inserir antes ou depois, e se você deseja inserir depois ou antes que ele:
// 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);
Solução de problemas
As formas aparecerão em posições incorretas se as alterações não são concluídas com um UpdateShapePositions() ou Layout() operação.
A maioria dos outros problemas são causados por pontos de inserção fique desalinhado, para que novas mensagens ou fragmentos teria que cruze sobre os outros.Os sintomas podem ser que nenhuma alteração é realizada, ou uma exceção é lançada.A exceção não pode ser lançada até que o UpdateShapePositions() ou Layout() operação é executada.
Consulte também
Referência
Microsoft.VisualStudio.Uml.Interactions
Conceitos
Diagramas e modelos UML estendendo
Como: definir um comando de Menu em um diagrama de modelagem
Como: definir um Item da caixa de ferramentas de modelagem de personalizado