Regras de propagam alterações dentro do modelo
Você pode criar uma regra de armazenamento para propagar uma alteração de um elemento para outro na visualização e modelagem SDK (VMSDK).Quando ocorre uma alteração a qualquer elemento no armazenamento, as regras estão programadas para ser executado, geralmente quando a transação externa for confirmada.Existem diferentes tipos de regras para diferentes tipos de eventos, como, por exemplo, adicionando um elemento ou excluí-lo.Você pode anexar regras a tipos específicos de elementos, formas ou diagramas.Muitos recursos internos são definidos pelas regras: por exemplo, regras garantem que um diagrama é atualizado quando o modelo é alterado.Você pode personalizar sua linguagem específica de domínio adicionando suas próprias regras.
Regras de armazenamento são particularmente úteis para propagar as alterações dentro do armazenamento – ou seja, altera para elementos de modelo, relacionamentos, formas ou conectores e seu domínio de propriedades.As regras não são executados quando o usuário aciona os comandos Desfazer ou refazer.Em vez disso, o Gerenciador de transações certifica-se de que o conteúdo do armazenamento é restaurado ao estado correto.Se você deseja propagar alterações para recursos fora do armazenamento, use a armazenar eventos.Para obter mais informações, consulte Manipuladores de eventos propagam alterações fora do modelo.
Por exemplo, suponha que você deseja 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ê poderia escrever um AddRule e associá-lo a ExampleDomainClass.Você poderia escrever o 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 somente de elementos dentro do armazenamento; ou seja, a regra deve alterar apenas os elementos de modelo, relacionamentos, formas, conectores, diagramas ou suas propriedades.Se você deseja propagar alterações para recursos fora do armazenamento, defina a armazenar eventos.Para mais informações, consulte: Manipuladores de eventos propagam alterações fora do modelo. |
Para definir uma regra
Definir a regra como uma classe prefixado com o RuleOn atributo.O atributo associa a regra de uma de suas classes de domínio, relacionamentos ou elementos de diagrama.A regra será aplicada a cada instância dessa classe, que pode ser abstrato.
Registre-se a regra de disponibilizá-lo para o conjunto retornado por GetCustomDomainModelTypes() na sua classe de modelo de domínio.
Derivar a classe de regra de uma dentre as classes abstratas de regra e escrever o código do método de execução.
As seções a seguir descrevem essas etapas mais detalhadamente.
Para definir uma regra em uma classe de domínio
Em um arquivo de código personalizado, definir uma classe e um prefixo 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 entidade no primeiro parâmetro pode ser uma classe de domínio, a relação de domínio, a forma, a conector ou o diagrama.Normalmente, você aplica regras às relações e classes de domínio.
The FireTime is usually TopLevelCommit.Isso garante que a regra é executada somente após todas as principais alterações da transação foram feitas.As alternativas são embutidas, que será executada a regra logo após a alteração; e LocalCommit, que executa a regra no final da transação atual (que pode não ser o mais externo).Você também pode definir a prioridade de uma regra para afetar seus pedidos na fila, mas este é um método confiável de atingir o resultado que necessário.
Você pode especificar uma classe abstrata como o tipo de entidade.
A regra se aplica a todas as instâncias da classe de entidade.
O valor padrão para FireTime é TimeToFire.TopLevelCommit.Isso faz com que a regra a ser executado quando a transação externa for confirmada.Uma alternativa é TimeToFire.Inline.Isso faz com que a regra a ser executada logo após o evento de disparo.
Para registrar a regra
Adiciona a sua classe de regra à lista de tipos retornados por GetCustomDomainModelTypes no 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, olhe dentro do arquivo.Dsl\GeneratedCode\DomainModel.cs
Escreva esse código em um arquivo de código personalizado em seu projeto DSL.
Escrever o código da regra
Derive a classe de regra de uma das seguintes classes base:
Classe base
Disparador
É adicionada a um elemento, link ou forma.
Use esta opção para detectar novas relações, com novos elementos.
Um valor de propriedade de domínio é alterado.O argumento do método fornece os valores novos e antigos.
Para formas, esta regra for acionada quando interno AbsoluteBounds alterações de propriedade, se a forma é movida.
Em muitos casos, é mais conveniente substituir OnValueChanged ou OnValueChanging no manipulador de propriedade.Esses métodos são chamados imediatamente antes e depois da alteração.Por outro lado, a regra é executada normalmente no final da transação.Para obter mais informações, consulte Manipuladores de alteração de valor de propriedade de domínio.
ObservaçãoEsta regra não é disparada quando um link é criado ou excluído.Em vez disso, escrever um AddRule e um DeleteRule para a relação de domínio.Acionado quando um elemento ou link está prestes a ser excluído.A propriedade ModelElement.IsDeleting é verdadeira até o final da transação.
Executada quando um elemento ou link foi excluído.A regra é executada depois que todas as outras regras tiverem sido executadas, incluindo o DeletingRules.ModelElement.IsDeleting é falso e ModelElement.IsDeleted é verdadeiro.Para permitir um desfazer subseqüente, o elemento não é efetivamente removido da memória, mas ele é removido do Store.ElementDirectory.
Um elemento é movido de um armazenamento partição para outra.
(Observe que isso não está relacionado à posição de uma forma gráfica).
Essa regra se aplica apenas às relações entre domínios.Se você atribuir explicitamente um elemento de modelo para uma das extremidades de um link é disparado.
Acionado quando a ordem dos links para ou de um elemento é alterada usando os métodos MoveBefore ou MoveToIndex em um link.
Executado quando uma transação é criada.
Executado quando a transação está prestes a ser confirmada.
Executado quando a transação está prestes a ser revertida.
Cada classe possui um método que você substituir.Tipo de override na sua classe detecte.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 disparar muitas regras.Normalmente, as regras são executadas quando a transação externa for confirmada.Eles são executados em uma ordem não especificada.
Uma regra é sempre executada dentro de uma transação.Portanto, você não precisará criar uma nova transação para fazer alterações.
Regras não serão executadas quando uma transação é revertida, ou quando as operações de desfazer ou refazer serão realizadas.Essas operações redefinir todo o conteúdo do armazenamento ao seu estado anterior.Portanto, se sua regra altera o estado de qualquer coisa fora do armazenamento, ele talvez não tenha em synchronism com o armazenamento de conteúdo.Para atualizar o estado fora do armazenamento, é 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 carregando ou salvando está em andamento, use store.TransactionManager.CurrentTransaction.IsSerializing.
Se o código da sua regra cria mais disparadores de regra, eles serão adicionados ao final da lista de acionamento e serão executados antes de concluída a transação.DeletedRules são executados após todas as outras regras.Uma regra pode executar muitas vezes em uma transação, uma vez para cada alteração.
Para passar informações para e de regras, você pode armazenar informações no TransactionContext.Este é apenas um dicionário que será mantido durante a transação.Ele é descartado quando a transação termina.Os argumentos do evento em cada regra fornecem acesso a ele.Lembre-se de que as regras não são executadas em uma ordem previsível.
Usar regras após considerar outras alternativas.Por exemplo, se você quiser atualizar uma propriedade quando um valor é alterado, considere o uso de uma propriedade calculada.Se você deseja 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 um OnValueChanged manipulador para a propriedade.Para obter mais informações, consulte Respondendo a e propagação de alterações.
Exemplo
O exemplo a seguir atualiza uma propriedade quando uma relação de domínio é instanciada para vincular os dois elementos.A regra será acionada não apenas quando o usuário cria um link em um diagrama, mas também se o código de programa cria um vínculo.
Para testar este exemplo, crie uma DSL usando o modelo de fluxo de tarefas de solução e insira o código a seguir em um arquivo no projeto Dsl.Construir e executar a solução e abrir o arquivo de exemplo no projeto Debugging.Desenhe um Link de comentário entre uma forma de comentário e um elemento de fluxo.O texto no comentário muda para informar sobre o elemento mais recente que você conectou a ele.
Na prática, você geralmente escreveria uma 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();
}
}
}