规则在模型内部传播更改

在可视化可以创建存储规则传播从一个元素的更改为另一个和建模 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. 注册规则通过将它添加到域模型类的 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 或 OnValueChanging 在属性处理程序会更方便。这些方法调用之前直接和更改之后的。相反,规则通常运行在事务末尾。有关更多信息,请参见 域属性值更改处理程序

    说明说明
    ,当 LINK 创建或删除时,此规则不会触发。相反,编写 AddRule 和 DeleteRule 域关系的。

    DeletingRule

    触发,当元素或链接将被删除。属性 ModelElement.IsDeleting 为 true 直到该事务的末尾。

    DeleteRule

    执行,当元素或链接已删除。规则执行,在其他规则执行后,包括 DeletingRules。ModelElement.IsDeleting 是错误的,因此, ModelElement.IsDeleted 为 true。若要允许随后请取消,则组件从内存实际上不会移除,但是,它从 Store.ElementDirectory 中移除。

    MoveRule

    元素从一个存储分区移动到另一个。

    (请注意这与图形形状的位置无关。)

    RolePlayerChangeRule

    此规则仅适用于域关系。,如果您显式分配一个模型元素指向链接,的任何一端已被触发。

    RolePlayerPositionChangeRule

    触发使用在链接,的 MoveBefore 或 MoveToIndex 方法时,排序来回元素的链接进行更改。

    TransactionBeginningRule

    执行,在事务中创建。

    TransactionCommittingRule

    执行,则该事务将被提交。

    TransactionRollingBackRule

    执行,则该事务将被回滚。

  • 每个类可以重写的方法。键入在类的 override 发现它。此方法的参数标识要更改的元素。

以下几点规则的通知:

  1. 设置在事务中的更改可能触发多个规则。通常,那么,当在最外层的事务提交时,这些规则执行。按未指定的顺序执行。

  2. 规则始终是在事务内。因此,不必创建新的事务进行更改。

  3. 规则,不会执行在事务回滚时,或者,在撤消或重做操作执行时。这些操作重置存储的所有内容到以前的状态。因此,因此,如果规则更改任何内容的状态在存储外,它与存储目录的同相可能不会保留。若要更新在存储外的状态,使用事件最好。有关更多信息,请参见 事件处理程序在模型外部传播更改

  4. ,在设计从文件时,加载某些规则执行。若要确定加载或保存是否正在进行,请使用 store.TransactionManager.CurrentTransaction.IsSerializing。

  5. 如果规则的代码创建多个规则触发器,它们将添加到激发的末尾列出并执行,在事务完成之前。DeletedRules 在其他规则在以后执行。一个规则可以运行在事务中多次,每项更改的一次。

  6. 来回转换规则若要通过信息,可以在 TransactionContext可以存储信息。这是在事务中维护的字典。,在事务末尾,它被释放。在每个规则的事件参数提供对它。确保规则未按可预测的顺序执行。

  7. 在考虑其他选择之后使用规则。例如,因此,如果要更新属性,该值更改时,请考虑使用一个计算的属性。如果要约束形状的大小或位置,请使用 BoundsRule。如果需要响应在属性值更改,添加一 OnValueChanged 处理程序添加到属性。有关更多信息,请参见 响应并传播更改

示例

,在域关系实例化链接两个组件时,下面的示例更新属性。规则将触发不仅,当用户创建关系图中的链接,,而且,如果程序代码创建链接。

使用任务流解决方案模板,若要测试此示例,请创建一个 DSL 并粘贴下面的代码隐藏文件在 DSL 项目。生成并运行解决方案,并在调试项目的示例文件。绘制注释链接在注释形状和流元素之间。在注释的文本变成有关最新元素的已连接到它。

实际上,通常会写 AddRule 的 DeleteRule。

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 约束形状位置和大小