Compartir a través de


Las reglas propagan los cambios dentro del modelo

Puede crear una regla de almacén para propagar un cambio a partir de un elemento a otro en el SDK de visualización y modelado (VMSDK). Cuando un cambio aparece a cualquier elemento del almacén, se programan las reglas para ejecutarse, normalmente cuando la transacción fuera es de confianza. Hay diferentes tipos de reglas para diferentes clases de eventos, como agregar un elemento, o eliminarlo. Puede asociar reglas a tipos específicos de elementos, de formas, o de diagramas. Muchas funciones integradas son definidas por reglas: por ejemplo, las reglas garantizan que un diagrama está actualizado cuando los cambios del modelo. Puede personalizar el lenguaje específico agregando dispone de reglas.

Las reglas de almacén son especialmente útiles para propagar cambios dentro del almacén (es decir, los cambios en los elementos de modelo, las relaciones, las formas o conectores, y sus propiedades de dominio. Las reglas no se ejecutan cuando el usuario invoca los comandos deshacer o de rehacer. En su lugar, el administrador de transacciones garantiza que el contenido del almacén se restablecen al estado correcto. Si desea propagar los cambios a los recursos fuera del almacén, el uso almacena eventos. Para obtener más información, vea Los controladores de eventos propagan cambios fuera del modelo.

Por ejemplo, suponga que desea especificar siempre que el usuario (o el código) cree un nuevo elemento de ExampleDomainClass escrito, un elemento adicional de otro tipo está creado en otra parte del modelo. Puede escribir un AddRule y asociarlo a ExampleDomainClass. Se escribe código en la regla para crear el 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();
   }
 }
}

Nota

El código de una regla debe cambiar el estado de solo elementos dentro del almacén; es decir, la regla debe cambiar solo los elementos de modelo, relaciones, formas, conectores, los diagramas, o sus propiedades.Si desea propagar los cambios a los recursos fuera del almacén, defina los eventos del almacén.Para obtener más información, vea Los controladores de eventos propagan cambios fuera del modelo.

para definir una regla

  1. Defina la regla como clase fija con el atributo de RuleOn . El atributo asocia la regla a una de las clases de dominio, las relaciones, o elementos del diagrama. La regla se aplicará a cada instancia de esta clase, que puede ser abstracta.

  2. Registre la regla agregándolo al conjunto devuelto por GetCustomDomainModelTypes() en la clase del modelo de dominio.

  3. Derive la clase de regla de alguna de las clases abstractas de regla, y escriba el código del método de la ejecución.

Las secciones siguientes se describen estos pasos con más detalle.

Para definir una regla en una clase de dominio

  • En un archivo de código personalizado, defina una clase y un prefijo en él con el atributo de RuleOnAttribute :

    [RuleOn(typeof(ExampleElement), 
         // Usual value – but required, because it is not the default:
         FireTime = TimeToFire.TopLevelCommit)] 
    class MyRule ...
    
  • El asunto escribir en el primer parámetro puede ser una clase de dominio, relación de dominio, una forma, un conector, o un diagrama. Normalmente, se aplican las reglas a las clases y relaciones de dominio.

    FireTime suele ser TopLevelCommit. Esto garantiza que la regla se ejecutará únicamente después de que todos los cambios principales de la transacción se ha creado. Las alternativas inline, que se ejecuta la regla poco después de cambio; y LocalCommit, que se ejecuta la regla al final de la transacción actual (que no sea la fuera). También puede establecer la prioridad de una regla para influir en el orden en la cola, pero éste es un método no confiable de lograr de resultado que necesita.

  • Puede especificar una clase abstracta mientras sujete el tipo.

  • La regla se aplica a todas las instancias de la clase subject.

  • el valor predeterminado para FireTime es TimeToFire.TopLevelCommit. Esto hace que la regla para ejecutarse cuando la transacción fuera es de confianza. una alternativa es TimeToFire.Inline. Esto hace que la regla para ejecutarse poco después del evento que se desencadena.

para registrar la regla

  • Agregue la clase de regla a la lista de tipos devueltos por GetCustomDomainModelTypes en el modelo de dominio:

    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();
       }
     }
    
  • Si no está seguro del nombre de la clase del modelo de dominio, busque en el archivo Dsl\GeneratedCode\DomainModel.cs

  • Escriba este código en un archivo de código personalizado en el proyecto ADSL.

para escribir el código de la regla

  • Derive la clase de regla de alguna de las siguientes clases base:

    Clase base

    Desencadenador

    AddRule

    se agrega un elemento, un vínculo, o una forma.

    utilice esto para detectar nuevas relaciones, además de nuevos elementos.

    ChangeRule

    Se cambia un valor de propiedad del dominio. El argumento de método proporciona los valores antiguos y nuevos.

    Para las formas, se desencadena esta regla cuando cambia la propiedad de AbsoluteBounds integrada, si se mueve la forma.

    En muchos casos, es más conveniente reemplazar OnValueChanged o OnValueChanging en el controlador de la propiedad. Estos métodos se llama inmediatamente antes y después del cambio. Por el contrario, la regla se ejecuta normalmente al final de la transacción. Para obtener más información, vea Controladores de los cambios de valor de propiedad de dominio.

    Nota

    Esta regla no se desencadena cuando se crea o elimina un vínculo.En su lugar, escriba AddRule y DeleteRule para la relación del dominio.

    DeletingRule

    Se desencadena cuando un elemento o un vínculo está a punto de ser eliminado. La propiedad ModelElement.IsDeleting es true hasta el final de la transacción.

    DeleteRule

    Ejecutará cuando se ha eliminado un elemento o un vínculo. La regla se ejecuta después de todas las demás reglas se ha ejecutado, incluidos DeletingRules. ModelElement.IsDeleting es false, y ModelElement.IsDeleted es true. Para que una operación de deshacer posterior, el elemento no se quita realmente de memoria, pero se quita de Store.ElementDirectory.

    MoveRule

    Un elemento se mueve de un elemento almacenada a otra.

    (Observe que no está relacionada con la posición gráfica de una forma.)

    RolePlayerChangeRule

    Esta regla se aplica sólo a las relaciones de dominio. Se desencadena si asignar explícitamente un elemento modelo cualquiera final de un vínculo.

    RolePlayerPositionChangeRule

    Se desencadena cuando la clasificación de vínculos a o desde un elemento se cambia mediante los métodos de MoveBefore o de MoveToIndex en un vínculo.

    TransactionBeginningRule

    Ejecutarse cuando se crea una transacción.

    TransactionCommittingRule

    Ejecutarse cuando la transacción está a punto de ser de confianza.

    TransactionRollingBackRule

    Ejecutarse cuando la transacción es de revertirse.

    • Cada clase tiene un método que se reemplace. escriba override en la clase para detectarla. El parámetro de este método identifica el elemento que se va a cambiar.

    Observe los siguientes sobre reglas:

    1. El conjunto de cambios en una transacción podría desencadenar muchas reglas. Normalmente, se ejecutan las reglas cuando la transacción fuera es de confianza. Se ejecutan en un orden no especificado.

    2. Una regla siempre se ejecuta dentro de una transacción. Por consiguiente, no tiene que crear una nueva transacción para realizar cambios.

    3. Las reglas no se ejecutan cuando una transacción se revierte, o cuando se realizan operaciones de deshacer o de rehacer. Estas operaciones se restablece todo el contenido del almacén a su estado anterior. Por consiguiente, si la regla cambia el estado nada fuera del almacén, no mantiene sincronismo con el contenido del almacén. Para actualizar el fuera de estado el almacén, es mejor utilizar eventos. Para obtener más información, vea Los controladores de eventos propagan cambios fuera del modelo.

    4. Se ejecutan algunas reglas cuando un modelo se carga desde un archivo. para determinar si carga o guarda está en curso, utilice store.TransactionManager.CurrentTransaction.IsSerializing.

    5. Si el código de la regla crea más desencadenadores de regla, se agregarán al final de la lista bounce, y ejecuta antes de que la transacción finaliza. DeletedRules se ejecuta después de todas las demás reglas. Una regla puede ejecutar varias veces en una transacción, una vez para cada cambio.

    6. Para pasar información entre reglas, puede almacenar información en TransactionContext. Éste es simplemente un diccionario que se mantiene durante la transacción. Se elimina cuando finaliza la transacción. Los argumentos de evento de cada regla proporcionan acceso al. Recuerde que las reglas no se ejecutan en un orden confiable.

    7. Reglas de uso después de ver otras alternativas. Por ejemplo, si desea actualizar una propiedad cuando un valor cambia, considere utilizar una propiedad calculada. Si desea restringir el tamaño o la ubicación de una forma, utilice BoundsRule. Si desea responder a un cambio en un valor de propiedad, agregue un controlador de OnValueChanged a la propiedad. Para obtener más información, vea Responder a los cambios y propagarlos.

    Ejemplo

    El ejemplo siguiente actualiza una propiedad cuando una relación de dominio se crea instancias para enlazar dos elementos. La regla se activan no sólo cuando el usuario establece relaciones en un diagrama, pero también si el código de programa vínculo.

    Para probar este ejemplo, cree un DSL mediante la plantilla de solución del flujo de la tarea, e inserte el código siguiente en un archivo del proyecto del ADSL. Compile y ejecute la solución, y abra el archivo de ejemplo en el proyecto de depuración. Dibuje un vínculo de comentario entre una forma de comentario y un elemento dinámico. El texto del comentario al informe en el elemento más reciente que se ha conectado con.

    En la práctica, normalmente se escribe un 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();
        }
      }
    
    }
    

    Vea también

    Conceptos

    Los controladores de eventos propagan cambios fuera del modelo

    Ubicación y tamaño de las reglas de restricción de formas BoundsRules