Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Você pode criar uma regra de armazenamento para propagar uma alteração de um elemento para outro no SDK de Visualização e Modelagem (VMSDK). Quando ocorre uma alteração em qualquer elemento na Loja, as regras são agendadas para serem executadas, geralmente quando a transação externa é confirmada. Há diferentes tipos de regras para diferentes tipos de eventos, como adicionar um elemento ou excluí-lo. Você pode anexar regras a tipos específicos de elementos, formas ou diagramas. Muitos recursos internos são definidos por regras: por exemplo, as regras garantem que um diagrama seja atualizado quando o modelo for alterado. Você pode personalizar o idioma específico do domínio adicionando suas próprias regras.
As regras de armazenamento são particularmente úteis para propagar alterações dentro do repositório - ou seja, alterações em elementos de modelo, relacionamentos, formas ou conectores e suas propriedades de domínio. As regras não são executadas quando o usuário invoca os comandos Desfazer ou Refazer. Em vez disso, o gerenciador de transações garante que o conteúdo da loja seja restaurado para o estado correto. Se quiser propagar alterações em recursos fora da loja, use Eventos da Loja. Para obter mais informações, consulte Manipuladores de eventos propagam alterações fora do modelo.
Por exemplo, suponha que você queira especificar que sempre que o usuário (ou seu código) cria um novo elemento do tipo ExampleDomainClass, um elemento adicional de outro tipo é criado em outra parte do modelo. Você pode escrever um AddRule e associá-lo a ExampleDomainClass. Você escreveria código na regra para criar o elemento adicional.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.Modeling;
namespace ExampleNamespace
{
// Attribute associates the rule with a domain class:
[RuleOn(typeof(ExampleDomainClass), FireTime=TimeToFire.TopLevelCommit)]
// The rule is a class derived from one of the abstract rules:
class MyAddRule : AddRule
{
// Override the abstract method:
public override void ElementAdded(ElementAddedEventArgs e)
{
base.ElementAdded(e);
ExampleDomainClass element = e.ModelElement;
Store store = element.Store;
// Ignore this call if we're currently loading a model:
if (store.TransactionManager.CurrentTransaction.IsSerializing)
return;
// Code here propagates change as required - for example:
AnotherDomainClass echo = new AnotherDomainClass(element.Partition);
echo.Name = element.Name;
echo.Parent = element.Parent;
}
}
// The rule must be registered:
public partial class ExampleDomainModel
{
protected override Type[] GetCustomDomainModelTypes()
{
List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
types.Add(typeof(MyAddRule));
// If you add more rules, list them here.
return types.ToArray();
}
}
}
Observação
O código de uma regra deve alterar o estado apenas dos elementos dentro da Loja; ou seja, a regra deve alterar apenas elementos do modelo, relações, formas, conectores, diagramas ou suas propriedades. Se você quiser propagar alterações para recursos fora da loja, defina Eventos da Loja. Para obter mais informações, consulte Manipuladores de eventos propagam alterações fora do modelo.
Para definir uma regra
Defina a regra como uma classe prefixada com o
RuleOnatributo. O atributo associa a regra a uma de suas classes de domínio, relacionamentos ou elementos de diagrama. A regra será aplicada a todas as instâncias desta classe, que podem ser abstratas.Registre a regra adicionando-a ao conjunto retornado por
GetCustomDomainModelTypes()em sua classe de modelo de domínio.Derive a classe rule de uma das classes Rule abstratas e escreva o código do método de execução.
As secções seguintes descrevem estes passos mais detalhadamente.
Para definir uma regra em uma classe de domínio
Em um arquivo de código personalizado, defina uma classe e prefixe-a com o RuleOnAttribute atributo:
[RuleOn(typeof(ExampleElement), // Usual value - but required, because it is not the default: FireTime = TimeToFire.TopLevelCommit)] class MyRule ...O tipo de assunto no primeiro parâmetro pode ser uma classe de domínio, relação de domínio, forma, conector ou diagrama. Normalmente, você aplica regras a classes e relacionamentos de domínio.
O
FireTimeé geralmenteTopLevelCommit. Isso garante que a regra seja executada somente depois que todas as alterações primárias da transação tiverem sido feitas. As alternativas são Inline, que executa a regra logo após a mudança; e LocalCommit, que executa a regra no final da transação atual (que pode não ser a mais externa). Você também pode definir a prioridade de uma regra para afetar sua ordem na fila, mas esse é um método não confiável para alcançar o resultado necessário.Você pode especificar uma classe abstrata como o tipo de assunto.
A regra aplica-se a todas as instâncias da classe de assunto.
O valor padrão para
FireTimeé TimeToFire.TopLevelCommit. Isso faz com que a regra seja executada quando a transação mais externa é confirmada. Uma alternativa é TimeToFire.Inline. Isso faz com que a regra seja executada logo após o evento de acionamento.
Para registrar a regra
Adicione sua classe de regra à lista de tipos retornados por
GetCustomDomainModelTypesem seu modelo de domínio:public partial class ExampleDomainModel { protected override Type[] GetCustomDomainModelTypes() { List<Type> types = new List<Type>(base.GetCustomDomainModelTypes()); types.Add(typeof(MyAddRule)); // If you add more rules, list them here. return types.ToArray(); } }Se você não tiver certeza do nome da sua classe de modelo de domínio, procure dentro do arquivo Dsl\GeneratedCode\DomainModel.cs
Escreva esse código em um arquivo de código personalizado em seu projeto DSL.
Para escrever o código da regra
Derive a classe de regra de qualquer uma das seguintes classes base.
Classe base Acionador AddRule Um elemento, link ou forma é adicionado.
Use isso para detetar novos relacionamentos, além de novos elementos.ChangeRule Um valor de propriedade de domínio é alterado. O argumento method fornece os valores antigos e novos.
Para formas, esta regra é acionada quando a propriedade incorporadaAbsoluteBoundsé alterada, caso a forma seja movida.
Em muitos casos, é mais conveniente substituirOnValueChangedouOnValueChangingno manipulador de propriedades. Esses métodos são chamados imediatamente antes e depois da alteração. Por outro lado, a regra geralmente é executada no final da transação. Para obter mais informações, consulte Manipuladores de alteração de valor de propriedade de domínio. Observação: Esta regra não é acionada quando um link é criado ou excluído. Em vez disso, escreva umAddRulee umDeleteRulepara a relação de domínio.DeletingRule Acionado quando um elemento ou link está prestes a ser excluído. A propriedade ModelElement.IsDeleting é verdadeiro até ao final da transação. DeleteRule Executado quando um elemento ou link foi excluído. A regra é executada depois que todas as outras regras foram executadas, incluindo DeletingRules. ModelElement.IsDeleting é falso e ModelElement.IsDeleted é verdadeiro. Para permitir um "Desfazer" subsequente, o elemento não é realmente removido da memória, mas é removido de Store.ElementDirectory. MoveRule Um elemento é movido de uma partição de armazenamento para outra.
(Observe que isso não está relacionado à posição gráfica de uma forma.)RolePlayerChangeRule Esta regra aplica-se apenas a relações de domínio. Ele é acionado se você atribuir explicitamente um elemento de modelo a qualquer extremidade de um link. RolePlayerPositionChangeRule Acionado quando a ordenação de links de ou para um elemento é alterada usando os métodos MoveBefore ou MoveToIndex em um link. TransactionBeginningRule Executado quando uma transação é criada. TransactionCommittingRule Executado quando a transação está prestes a ser confirmada. TransactionRollingBackRule Executado quando a transação está prestes a ser revertida. Cada classe tem um método que você substitui. Digite
overridena sua classe para descobri-la. O parâmetro desse método identifica o elemento que está sendo alterado.Observe os seguintes pontos sobre regras:
O conjunto de alterações em uma transação pode acionar muitas regras. Normalmente, as regras são executadas quando a transação mais externa é confirmada. Eles são executados em uma ordem não especificada.
Uma regra é sempre executada dentro de uma transação. Portanto, não é necessário criar uma nova transação para fazer alterações.
As regras não são executadas quando uma transação é revertida ou quando as operações Desfazer ou Refazer são executadas. Essas operações redefinem todo o conteúdo da Loja para seu estado anterior. Portanto, se a sua regra alterar o estado de qualquer coisa fora da Loja, ela pode não estar em sincronismo com o conteúdo da Loja. Para atualizar o estado fora da Loja, é melhor usar Eventos. Para obter mais informações, consulte Manipuladores de eventos propagam alterações fora do modelo.
Algumas regras são executadas quando um modelo é carregado do arquivo. Para determinar se o carregamento ou o salvamento estão em andamento, use
store.TransactionManager.CurrentTransaction.IsSerializing.Se o código da sua regra criar mais disparadores de regra, estes serão adicionados ao final da lista de execução e serão executados antes que a transação seja concluída. DeletedRules é executada depois de todas as outras regras. Uma regra pode ser executada muitas vezes em uma transação, uma vez para cada alteração.
Para passar informações de e para as regras, você pode armazenar informações no
TransactionContext. Este é apenas um dicionário que é mantido durante a transação. É eliminado quando a transação termina. Os argumentos de evento em cada regra fornecem acesso a ela. Lembre-se de que as regras não são executadas em uma ordem previsível.Use regras depois de considerar outras alternativas. Por exemplo, se você quiser atualizar uma propriedade quando um valor for alterado, considere o uso de uma propriedade calculada. Se quiser restringir o tamanho ou a localização de uma forma, use um
BoundsRule. Se você quiser responder a uma alteração no valor de uma propriedade, adicione umOnValueChangedmanipulador à propriedade. Para obter mais informações, consulte Respondendo e propagando alterações.
Example
O exemplo a seguir atualiza uma propriedade quando uma relação de domínio é instanciada para vincular dois elementos. A regra será desencadeada não apenas quando o utilizador criar um link num diagrama, mas também caso o código do programa crie um link.
Para testar este exemplo, crie uma DSL usando o modelo de solução Fluxo de Tarefas e insira o código a seguir em um arquivo no projeto Dsl. Crie e execute a solução e abra o arquivo de exemplo no projeto de depuração. Desenhe uma ligação de comentário entre uma forma de comentário e um elemento de fluxo. O texto no comentário é alterado para relatar o elemento mais recente ao qual você o conectou.
Na prática, você normalmente escreveria um DeleteRule para cada AddRule.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Modeling;
namespace Company.TaskRuleExample
{
[RuleOn(typeof(CommentReferencesSubjects))]
public class RoleRule : AddRule
{
public override void ElementAdded(ElementAddedEventArgs e)
{
base.ElementAdded(e);
CommentReferencesSubjects link = e.ModelElement as CommentReferencesSubjects;
Comment comment = link.Comment;
FlowElement subject = link.Subject;
Transaction current = link.Store.TransactionManager.CurrentTransaction;
// Don't want to run when we're just loading from file:
if (current.IsSerializing) return;
comment.Text = "Flow has " + subject.FlowTo.Count + " outgoing connections";
}
}
public partial class TaskRuleExampleDomainModel
{
protected override Type[] GetCustomDomainModelTypes()
{
List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
types.Add(typeof(RoleRule));
return types.ToArray();
}
}
}