重写和扩展生成的类

DSL 定义是一个平台,可用于基于特定领域语言构建一套功能强大的工具集。 可以通过重写和扩展从 DSL 定义生成的类来实现许多扩展和适应。 这些类不仅包括你在 DSL 定义关系图中显式定义的域类,还包括定义工具箱、资源管理器、序列化等的其他类。

扩展性机制

提供了多种机制来扩展生成的代码。

部分类中的方法重写

分部类定义允许在多个位置定义类。 这样,就可以将生成的代码与自己编写的代码分开。 在手动编写的代码中,可以重写由生成的代码继承的类。

例如,如果在 DSL 定义中定义了一个名为 Book域类,则可以编写添加重写方法的自定义代码:

public partial class Book
{
   protected override void OnDeleting()
   {
      MessageBox.Show("Deleting book " + this.Title);
      base.OnDeleting();
   }
}

注释

若要重写生成的类中的方法,请始终在与生成的文件分开的文件中编写代码。 通常,该文件包含在名为 CustomCode 的文件夹中。 如果对生成的代码进行更改,则从 DSL 定义重新生成代码时,它们将丢失。

若要发现可以替代的方法,请在类中键入 重写 ,后跟空格。 IntelliSense 工具提示将告诉你可以重写哪些方法。

双重派生类

生成的类中的大多数方法都继承自建模命名空间中的一组固定类。 但是,某些方法在生成的代码中定义。 通常,这意味着不能重写它们;不能在一个分部类中重写在同一类的另一个分部定义中定义的方法。

不过,可以通过为域类设置 Generates Double Derived 标志来替代这些方法。 这会导致生成两个类,一个是另一个抽象基类。 所有方法和属性定义都位于基类中,并且只有构造函数位于派生类中。

例如,在示例 Library.dsl 中 CirculationBook ,域类的属性 Generates``Double Derived 设置为 true。 该域类生成的代码包含两个类:

  • CirculationBookBase,它是一个抽象,其中包含所有方法和属性。

  • CirculationBook,派生自 CirculationBookBase. 它是空的,除了构造函数。

若要替代任何方法,请创建派生类的部分定义,例如 CirculationBook。 可以重写生成的方法和从建模框架继承的方法。

可以将此方法用于所有类型的元素,包括模型元素、关系、形状、关系图和连接线。 还可以替代其他生成的类的方法。 某些生成的类(如 ToolboxHelper)始终是双派生类。

自定义构造函数

不能重写构造函数。 即使在双派生类中,构造函数也必须位于派生类中。

如果要提供自己的构造函数,可以通过在 DSL 定义中为域类设置 Has Custom Constructor 来执行此作。 单击“ 转换所有模板”时,生成的代码将不包含该类的构造函数。 它将包含对缺失构造函数的调用。 这会导致生成解决方案时出现错误报告。 双击错误报告,查看生成的代码中的注释,说明应提供的内容。

在独立于生成的文件的文件中编写分部类定义,并提供构造函数。

标记的扩展点

标记的扩展点是 DSL 定义中的一个位置,你可以在其中设置属性或复选框来指示你将提供自定义方法。 自定义构造函数是一个示例。 其他示例包括将 Kind 域属性设置为“计算”或“自定义存储”,或在连接生成器中设置 “是自定义 ”标志。

在每种情况下,当设置选项并重新生成代码时,将会导致构建错误。 双击错误以查看您必须提供的说明性注释。

规则

事务管理器允许你定义在发生指定事件的事务结束前运行的规则,例如属性中的更改。 规则通常用于保持存储中不同元素之间的同步性。 例如,规则用于确保关系图显示模型的当前状态。

规则基于每个类定义,因此不必有代码来注册每个对象的规则。 有关详细信息,请参阅 规则在模型中传播更改

存储事件

建模存储提供了一种事件机制,可用于侦听存储中特定类型的更改,包括添加和删除元素、属性值更改等。 在进行更改的事务关闭后,将调用事件处理程序。 通常,这些事件用于更新存储区外部的资源。

.NET 事件

您可以订阅与形状相关的某些事件。 例如,可以侦听形状上的鼠标单击。 你需要编写代码,以订阅每个对象相关的事件。 此代码可以用 InitializeInstanceResources()的重写编写。

某些事件在 ShapeFields 上生成,这些事件用于在形状上绘制修饰器。 有关示例,请参阅 “如何:拦截对形状或修饰器的点击”

这些事件通常不会在事务内发生。 如果要在存储中进行更改,则应创建一个事务。