Поделиться через


Правила распространяют изменения в пределах модели

Можно создать правило хранилища передавать изменения от одного элемента к другому в зрительном образом и пакет SDK для моделирования (VMSDK).Если изменение происходит к любому элементу в хранилище, планируются правила выполняться, обычно при фиксации внешней транзакции.Различные типы правил для разных типов событий, как добавить элемент или удалить его.Можно вложить правила к конкретным типам элементов форм или диаграмма.Множество встроенных функций, определяются правилами: например, правил убедитесь, что схема обновляется, когда модель изменяется.Можно настраивать свой доменный язык путем добавления собственных правил.

Правила хранилища особенно полезны для распространения изменений в хранилища, т е изменения к элементам модели связей или соединителям фигурам и их свойствам домена.Правила не выполняется, когда пользователь вызывает команды отката или повтора.Вместо этого диспетчер транзакций гарантирует, что содержимое хранилища восстанавливаются к правильному состояние.Если необходимо передать изменения к ресурсам вне хранилища, используйте события хранилища.Дополнительные сведения см. в разделе Обработчики событий распространяют изменения за пределы модели.

Например, предположим, что нужно указать, что, когда пользователь (или код) создают новый элемент типа ExampleDomainClass, создается дополнительный элемент другого типа в другой части модели.Можно написать AddRule и связать его с ExampleDomainClass.Следует написать код в правиле создать дополнительный элемент.

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();
   }
 }
}
ПримечаниеПримечание

Код правила должен изменить состояние только тех элементов внутри хранилища; это значит, что правило должно изменяться только элементы модели отношений, фигуры соединители, схемы или их свойства.Если необходимо передать изменения к ресурсам вне хранилища, укажите события хранилища.Дополнительные сведения см. в разделе Обработчики событий распространяют изменения за пределы модели.

Определение правила

  1. Определите правило, что и класс присоединенный префикс RuleOn атрибут.Атрибут связывает правило с одним из классов, связей или доменных элементов схемы.Правило будет применено к каждому экземпляру этого класса, который может быть абстрактным.

  2. Зарегистрируйте правило, добавить его к набору, возвращаемому by GetCustomDomainModelTypes() в классе модели домена.

  3. Создайте класс правил из одного из абстрактных классов правил и напишите код метода выполнения.

В следующих разделах описываются эти шаги подробно.

Чтобы определить правила на доменном классе

  • В файле пользовательского кода, определите класс и префикс его с RuleOnAttribute атрибут:

    [RuleOn(typeof(ExampleElement), 
         // Usual value – but required, because it is not the default:
         FireTime = TimeToFire.TopLevelCommit)] 
    class MyRule ...
    
  • Подчиненных тип в первый параметр может быть доменным классом, доменной ссылкой, формой соединителем или схеме.Обычно применяются правила к доменным классам и связей.

    FireTime обычно TopLevelCommit.Это гарантирует, что правило выполняется только после того, как были выполнены все основные изменения транзакции.Альтернативные встроенный, который выполняет правило вскоре после изменения; и LocalCommit, которое выполняет правила в конце текущей транзакции (это может не быть внешней).Можно также задать приоритет правила повлиять на его упорядочивание в очередь, но это ненадежный метод достижения результата.

  • Можно определить абстрактный класс как тип субъекта.

  • Правило применяется ко всем экземплярам подчиненного класса.

  • Значение по умолчанию FireTime TimeToFire.TopLevelCommit.Это приводит к тому, что правило должно быть выполнено при фиксации внешней транзакции.Альтернативы TimeToFire.Inline.Это приводит к тому, что правило должно быть выполнено вскоре после активируя события.

Регистрация правило

  • Добавьте этот класс к списку типов, возвращаемых которым следуют правила GetCustomDomainModelTypes в модели домена.

    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();
       }
     }
    
  • Если вы не уверены имени класса модели домена, то поиск в файл Dsl\GeneratedCode\DomainModel.cs

  • Запишите этот код в файле пользовательского кода в проекте DSL.

Правила написания кода

  • Создайте класс правил из одного из следующих базовых классов:

    Базовый класс

    Триггер

    AddRule

    Элемент соединения или форма.

    Используйте его, чтобы определить новые связи, в дополнение к новым элементам.

    ChangeRule

    Значение свойства домена изменено.Аргумент метода содержит старое и новое значения.

    Фигур, если активировано это правило встроенного AbsoluteBounds изменении свойства, если фигура перемещена.

    Во многих случаях более удобно переопределить OnValueChanged OR OnValueChanging в обработчике свойств.Эти методы вызываются непосредственно перед и после изменения.Напротив, правило обычно выполняется в конце транзакции.Дополнительные сведения см. в разделе Обработчики изменений значений свойств доменов.

    ПримечаниеПримечание
    Это правило не активирована при создании или удалена связь.Вместо этого пишите AddRule и a DeleteRule для доменной ссылки.

    DeletingRule

    Активированы, когда элемент или намерении удалить связь.Свойство ModelElement.IsDeleting true до конца транзакции.

    DeleteRule

    Выполняется, когда элемент или связи были удалены.Правило выполняется после того, как все другие правила был выполнен, включая DeletingRules.ModelElement.IsDeleting false, а ModelElement.IsDeleted true.Допускать последующий откат, элемент не удален из памяти, но он удаляется из Store.ElementDirectory.

    MoveRule

    Элемент был перемещен из одного раздела хранения в другой.

    (Обратите внимание, что это не относится к графической положения фигур.)

    RolePlayerChangeRule

    Это правило применяется только к доменным ссылкам.Если явно присвоить его активирован элемент модели, к какому концу отношения.

    RolePlayerPositionChangeRule

    Активированы, когда порядок связей или из элементов изменен с помощью методов MoveBefore или MoveToIndex в связи.

    TransactionBeginningRule

    Выполняется, если транзакция создана.

    TransactionCommittingRule

    Выполняется при намерении фиксации транзакции.

    TransactionRollingBackRule

    Выполняется, когда транзакция к откату.

  • Каждый класс содержит метод, который необходимо переопределить.Тип override в классе, который нужно искать его.Параметр данного метода указывает элемент, который необходимо изменить.

Обратите внимание на следующие моменты о правилах:

  1. Набор изменений в транзакции может активировать много правил.Обычно, когда правила выполняются внешней фиксации транзакции.Они выполняются в unspecified порядке.

  2. Правила всегда выполняется в транзакции.Поэтому не следует создать новую транзакцию, чтобы внести изменения.

  3. Правила, не выполняются, когда транзакция откаченна или когда выполняются операции отката или повтора.Эти операции сбросят все содержимое хранилища в предыдущее состояние.Поэтому, если правило ничего изменяет состояние вне хранилища, он может не иметь синхронизме с содержимым хранилища.Чтобы обновить состояние ожидания восстановления, лучше использовать события.Дополнительные сведения см. в разделе Обработчики событий распространяют изменения за пределы модели.

  4. Некоторые правила выполняются, когда модель загружается из файла.Чтобы определить, является ли загрузке или сохранении выполняется, используйте store.TransactionManager.CurrentTransaction.IsSerializing.

  5. Если код пользовательского правила создает несколько триггеров правила, они будут добавлены в конец списка включений и выполняются до завершения транзакции.DeletedRules выполняется после всех других правил.Одно правило может выполняться много раз в транзакции по одному разу для каждого изменения.

  6. Для передачи информации в и из правил можно хранить информацию в TransactionContext.Это просто словарь, используемый во время транзакции.Он удален, когда транзакция завершается.Аргументы события для каждого правила обеспечивают доступ к нему.Помните, что правила не выполняются в прогнозируемом порядке.

  7. Используйте правила после рассмотрения других вариантов.Например, если нужно обновить свойство, то при изменении значения, рассмотрите возможность использования вычисленное свойство.Если необходимо ограничить размер или расположение фигур, используйте a BoundsRule.Если требуется ответ на изменение значения свойства, добавьте OnValueChanged обработчик к свойству.Дополнительные сведения см. в разделе Реагирование на изменения и их распространение.

Пример

В следующем примере обновляется свойство, если доменная связь создается для связывания 2 элементов.Правило не будет активировано, только если пользователь создает связь на схеме, а также если программный код создает ссылку.

Чтобы проверить этот пример, создайте DSL, используя шаблон решения потока задачи, и вставьте следующий код в файл в проекте Dsl.Постройте и запустите решение и открыть пример файла проекта для отладки.Создайте ссылку комментария между формой комментариев и элементом потока.Текст в комментарии изменений в отчет последний элемент, подключались к.

На практике обычно написать DeleteRule для каждого 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();
    }
  }

}

См. также

Основные понятия

Обработчики событий распространяют изменения за пределы модели

Класс BoundsRules ограничивает расположение и размеры фигур