Regras propagam alterações dentro do modeloRules Propagate Changes Within the Model

Você pode criar uma regra de repositório para propagar uma alteração de um elemento para outro no SDK de modelagem e visualização (VMSDK).You can create a store rule to propagate a change from one element to another in Visualization and Modeling SDK (VMSDK). Quando ocorre uma alteração em qualquer elemento da loja, as regras são agendadas para serem executadas, geralmente quando a transação mais externa é confirmada.When a change occurs to any element in the Store, rules are scheduled to be executed, usually when the outermost transaction is committed. Há diferentes tipos de regras para diferentes tipos de eventos, como adicionar um elemento ou excluí-lo.There are different types of rules for different kinds of events, such as adding an element, or deleting it. Você pode anexar regras a tipos específicos de elementos, formas ou diagramas.You can attach rules to specific types of elements, shapes, or diagrams. Muitos recursos internos são definidos por regras: por exemplo, as regras garantem que um diagrama seja atualizado quando o modelo for alterado.Many built-in features are defined by rules: for example, rules ensure that a diagram is updated when the model changes. Você pode personalizar sua linguagem específica de domínio adicionando suas próprias regras.You can customize your domain-specific language by adding your own rules.

As regras de armazenamento são particularmente úteis para a propagação de alterações dentro da loja, ou seja, alterações em elementos de modelo, relações, formas ou conectores e suas propriedades de domínio.Store rules are particularly useful for propagating changes inside the store - that is, changes to model elements, relationships, shapes or connectors, and their domain properties. As regras não são executadas quando o usuário invoca os comandos desfazer ou refazer.Rules do not run when the user invokes the Undo or Redo commands. Em vez disso, o Gerenciador de transações garante que o conteúdo da loja seja restaurado para o estado correto.Instead, the transaction manager makes sure that the store contents are restored to the correct state. Se você quiser propagar alterações para recursos fora da loja, use armazenar eventos.If you want to propagate changes to resources outside the store, use Store Events. Para obter mais informações, consulte manipuladores de eventos propagar alterações fora do modelo.For more information, see Event Handlers Propagate Changes Outside the Model.

Por exemplo, suponha que você queira especificar que sempre que o usuário (ou seu código) criar um novo elemento do tipo ExampleDomainClass, um elemento adicional de outro tipo será criado em outra parte do modelo.For example, suppose that you want to specify that whenever the user (or your code) creates a new element of type ExampleDomainClass, an additional element of another type is created in another part of the model. Você poderia escrever uma addrule e associá-la a ExampleDomainClass.You could write an AddRule and associate it with ExampleDomainClass. Você escreveria o código na regra para criar o elemento adicional.You would write code in the rule to create the additional element.

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 de modelo, relações, formas, conectores, diagramas ou suas propriedades.The code of a rule should change the state only of elements inside the Store; that is, the rule should change only model elements, relationships, shapes, connectors, diagrams, or their properties. Se você quiser propagar alterações para recursos fora da loja, defina armazenar eventos.If you want to propagate changes to resources outside the store, define Store Events. Para obter mais informações, consulte manipuladores de eventos propagar alterações fora do modelo.For more information, see Event Handlers Propagate Changes Outside the Model.

Para definir uma regraTo define a rule

  1. Defina a regra como uma classe prefixada com o RuleOn atributo.Define the rule as a class prefixed with the RuleOn attribute. O atributo associa a regra a uma de suas classes de domínio, relações ou elementos de diagrama.The attribute associates the rule with one of your domain classes, relationships, or diagram elements. A regra será aplicada a todas as instâncias dessa classe, que podem ser abstratas.The rule will be applied to every instance of this class, which may be abstract.

  2. Registre a regra adicionando-a ao conjunto retornado por GetCustomDomainModelTypes() em sua classe de modelo de domínio.Register the rule by adding it to the set returned by GetCustomDomainModelTypes() in your domain model class.

  3. Derive a classe de regra de uma das classes de regra abstrata e escreva o código do método de execução.Derive the rule class from one of the abstract Rule classes, and write the code of the execution method.

    As seções a seguir descrevem essas etapas mais detalhadamente.The following sections describe these steps in more detail.

Para definir uma regra em uma classe de domínioTo define a rule on a domain class

  • Em um arquivo de código personalizado, defina uma classe e Prefixe-a com o RuleOnAttribute atributo:In a custom code file, define a class and prefix it with the RuleOnAttribute attribute:

    [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, relação de domínio, forma, conector ou diagrama.The subject type in the first parameter can be a domain class, domain relationship, shape, connector, or diagram. Normalmente, você aplica regras a relações e classes de domínio.Usually, you apply rules to domain classes and relationships.

    Normalmente, o FireTime é TopLevelCommit .The FireTime is usually TopLevelCommit. Isso garante que a regra seja executada somente depois que todas as alterações principais da transação tiverem sido feitas.This ensures that the rule is executed only after all the primary changes of the transaction have been made. As alternativas são embutidas, o que executa 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 a mais externa).The alternatives are Inline, which executes the rule soon after the change; and LocalCommit, which executes the rule at the end of the current transaction (which might not be the outermost). Você também pode definir a prioridade de uma regra para afetar sua ordenação na fila, mas esse é um método não confiável de obter o resultado necessário.You can also set the priority of a rule to affect its ordering in the queue, but this is an unreliable method of achieving the result you require.

  • Você pode especificar uma classe abstrata como o tipo de entidade.You can specify an abstract class as the subject type.

  • A regra se aplica a todas as instâncias da classe Subject.The rule applies to all instances of the subject class.

  • O valor padrão para FireTime é TimeToFire. TopLevelCommit.The default value for FireTime is TimeToFire.TopLevelCommit. Isso faz com que a regra seja executada quando a transação mais externa é confirmada.This causes the rule to be executed when the outermost transaction is committed. Uma alternativa é TimeToFire. Inline.An alternative is TimeToFire.Inline. Isso faz com que a regra seja executada logo após o evento de disparo.This causes the rule to be executed soon after the triggering event.

Para registrar a regraTo register the rule

  • Adicione sua classe de regra à lista de tipos retornados pelo GetCustomDomainModelTypes em seu modelo de domínio:Add your rule class to the list of types returned by GetCustomDomainModelTypes in your domain model:

    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.csIf you are not sure of the name of your domain model class, look inside the file Dsl\GeneratedCode\DomainModel.cs

  • Escreva este código em um arquivo de código personalizado em seu projeto DSL.Write this code in a custom code file in your DSL project.

Para gravar o código da regraTo write the code of the rule

  • Derive a classe de regra de uma das seguintes classes base:Derive the rule class from one of the following base classes:

    Classe baseBase class GatilhoTrigger
    AddRule Um elemento, link ou forma é adicionado.An element, link, or shape is added.

    Use isso para detectar novas relações, além de novos elementos.Use this to detect new relationships, in addition to new elements.
    ChangeRule Um valor de propriedade de domínio é alterado.A domain property value is changed. O argumento do método fornece os valores novos e antigos.The method argument provides the old and new values.

    Para formas, essa regra é disparada quando a AbsoluteBounds propriedade interna é alterada, se a forma for movida.For shapes, this rule is triggered when the built-in AbsoluteBounds property changes, if the shape is moved.

    Em muitos casos, é mais conveniente substituir OnValueChanged ou OnValueChanging no manipulador de propriedades.In many cases, it is more convenient to override OnValueChanged or OnValueChanging in the property handler. Esses métodos são chamados imediatamente antes e depois da alteração.These methods are called immediately before and after the change. Por outro lado, a regra geralmente é executada no final da transação.By contrast, the rule usually runs at the end of the transaction. Para obter mais informações, consulte manipuladores de alteração de valor de propriedade de domínio.For more information, see Domain Property Value Change Handlers. Observação: Essa regra não é disparada quando um link é criado ou excluído.Note: This rule is not triggered when a link is created or deleted. Em vez disso, grave um AddRule e um DeleteRule para o relacionamento de domínio.Instead, write an AddRule and a DeleteRule for the domain relationship.
    DeletingRule Disparado quando um elemento ou link está prestes a ser excluído.Triggered when an element or link is about to be deleted. A Propriedade ModelElement. isdeleble é true até o final da transação.The property ModelElement.IsDeleting is true until the end of the transaction.
    DeleteRule Executado quando um elemento ou link foi excluído.Performed when an element or link has been deleted. A regra é executada Depois que todas as outras regras forem executadas, incluindo DeletingRules.The rule is executed after all other rules have been executed, including DeletingRules. ModelElement. isexcluindo é false e ModelElement. IsDeleted é true.ModelElement.IsDeleting is false, and ModelElement.IsDeleted is true. Para permitir um desfazer subsequente, o elemento não é realmente removido da memória, mas é removido de Store. ElementDirectory.To allow for a subsequent Undo, the element is not actually removed from the memory, but it is removed from Store.ElementDirectory.
    MoveRule Um elemento é movido de uma partição de armazenamento para outra.An element is moved from one store partition to another.

    (Observe que isso não está relacionado à posição gráfica de uma forma.)(Notice that this is not related to the graphical position of a shape.)
    RolePlayerChangeRule Essa regra se aplica somente a relações de domínio.This rule applies only to domain relationships. Ele será disparado se você atribuir explicitamente um elemento de modelo para o final de um link.It is triggered if you explicitly assign a model element to either end of a link.
    RolePlayerPositionChangeRule Disparado quando a ordenação de links para ou de um elemento é alterada usando os métodos MoveBefore ou MoveToIndex em um link.Triggered when the ordering of links to or from an element is changed using the MoveBefore or MoveToIndex methods on a link.
    TransactionBeginningRule Executado quando uma transação é criada.Executed when a transaction is created.
    TransactionCommittingRule Executado quando a transação está prestes a ser confirmada.Executed when the transaction is about to be committed.
    TransactionRollingBackRule Executado quando a transação está prestes a ser revertida.Executed when the transaction is about to be rolled back.
  • Cada classe tem um método que você substitui.Each class has a method that you override. Digite override sua classe para descobri-la.Type override in your class to discover it. O parâmetro desse método identifica o elemento que está sendo alterado.The parameter of this method identifies the element that is being changed.

    Observe os seguintes pontos sobre as regras:Notice the following points about rules:

  1. O conjunto de alterações em uma transação pode disparar muitas regras.The set of changes in a transaction might trigger many rules. Normalmente, as regras são executadas quando a transação mais externa é confirmada.Usually, the rules are executed when the outermost transaction is committed. Eles são executados em uma ordem não especificada.They are executed in an unspecified order.

  2. Uma regra é sempre executada dentro de uma transação.A rule is always executed inside a transaction. Portanto, você não precisa criar uma nova transação para fazer alterações.Therefore, you do not have to create a new transaction to make changes.

  3. As regras não são executadas quando uma transação é revertida ou quando as operações de desfazer ou refazer são executadas.Rules are not executed when a transaction is rolled back, or when the Undo or Redo operations are performed. Essas operações redefinem todo o conteúdo da loja para seu estado anterior.These operations reset all the content of the Store to its previous state. Portanto, se a regra alterar o estado de qualquer coisa fora da loja, ela poderá não manter em sincronização com o conteúdo da loja.Therefore, if your rule changes the state of anything outside the Store, it might not keep in synchronism with the Store content. Para atualizar o estado fora da loja, é melhor usar eventos.To update state outside the Store, it is better to use Events. Para obter mais informações, consulte manipuladores de eventos propagar alterações fora do modelo.For more information, see Event Handlers Propagate Changes Outside the Model.

  4. Algumas regras são executadas quando um modelo é carregado do arquivo.Some rules are executed when a model is loaded from file. Para determinar se o carregamento ou salvamento está em andamento, use store.TransactionManager.CurrentTransaction.IsSerializing .To determine whether loading or saving is in progress, use store.TransactionManager.CurrentTransaction.IsSerializing.

  5. Se o código da regra criar mais gatilhos de regra, eles serão adicionados ao final da lista de acionamento e serão executados antes da conclusão da transação.If the code of your rule creates more rule triggers, they will be added to the end of the firing list, and will be executed before the transaction completes. DeletedRules são executadas após todas as outras regras.DeletedRules are executed after all other rules. Uma regra pode ser executada muitas vezes em uma transação, uma vez para cada alteração.One rule can run many times in a transaction, one time for each change.

  6. Para passar informações de e para regras, você pode armazenar informações no TransactionContext .To pass information to and from rules, you can store information in the TransactionContext. Esse é apenas um dicionário que é mantido durante a transação.This is just a dictionary that is maintained during the transaction. Ela é descartada quando a transação termina.It is disposed when the transaction ends. Os argumentos de evento em cada regra fornecem acesso a ele.The event arguments in each rule provide access to it. Lembre-se de que as regras não são executadas em uma ordem previsível.Remember that rules are not executed in a predictable order.

  7. Use regras depois de considerar outras alternativas.Use rules after considering other alternatives. Por exemplo, se você quiser atualizar uma propriedade quando um valor for alterado, considere usar uma propriedade calculada.For example, if you want to update a property when a value changes, consider using a calculated property. Se você quiser restringir o tamanho ou o local de uma forma, use um BoundsRule .If you want to constrain the size or location of a shape, use a BoundsRule. Se você quiser responder a uma alteração em um valor de propriedade, adicione um OnValueChanged manipulador à propriedade.If you want to respond to a change in a property value, add an OnValueChanged handler to the property. Para obter mais informações, consulte respondendo e propagando alterações.For more information, see Responding to and Propagating Changes.

ExemploExample

O exemplo a seguir atualiza uma propriedade quando uma relação de domínio é instanciada para vincular dois elementos.The following example updates a property when a domain relationship is instantiated to link two elements. A regra será disparada não apenas quando o usuário criar um link em um diagrama, mas também se o código do programa criar um link.The rule will be triggered not only when the user creates a link on a diagram, but also if program code creates a link.

Para testar este exemplo, crie uma DSL usando o modelo de solução de fluxo de tarefas e insira o código a seguir em um arquivo no projeto DSL.To test this example, create a DSL using the Task Flow solution template, and insert the following code in a file in the Dsl project. Compile e execute a solução e abra o arquivo de exemplo no projeto de depuração.Build and run the solution, and open the Sample file in the Debugging project. Desenhe um link de comentário entre uma forma de comentário e um elemento de fluxo.Draw a Comment Link between a Comment shape and a flow element. O texto no comentário muda para o relatório no elemento mais recente ao qual você o conectou.The text in the comment changes to report on the most recent element that you have connected it to.

Na prática, você normalmente escreveria um DeleteRule para cada addrule.In practice, you would usually write a DeleteRule for every 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();
    }
  }

}

Confira tambémSee also