域特定语言 (DSL) 解决方案将生成可用于在 Visual Studio 中读取和更新 DSL 实例的 API。 此 API 将定义在从 DSL 定义生成的代码中。 本主题介绍了生成的 API。
示例解决方案:组件图
若要创建作为本主题中大多数示例的源的解决方案,请从**“组件模型”**解决方案模板中创建 DSL。 这是在创建新 DSL 解决方案时显示的标准模板之一。
备注
组件图 DSL 模板与可在 Visual Studio 旗舰版 中使用“体系结构”菜单创建的 UML 组件图无关。在“新建项目”对话框中,展开“其他项目类型\扩展性”,然后单击“域特定语言设计器”。
如果你不熟悉此解决方案模板,请按 F5 并进行试验。 特别注意,可通过将端口工具拖动到组件上来创建端口,并可连接端口。
DSL 解决方案的结构
Dsl 项目定义用于 DSL 的 API。 DslPackage 项目定义它与 Visual Studio 集成的方式。 还可添加你自己的项目,这些项目还可包含从模型生成的代码。
代码指令
其中每个项目的大多数代码都从 Dsl\DslDefinition.dsl 中生成。 生成的代码位于 Generated Code 文件夹中。 若要查看生成的文件,请单击生成 .tt 文件旁边的**“[+]”**。
建议你检查生成的代码以帮助你了解 DSL。 若要查看生成的文件,请在“解决方案资源管理器”中展开 *.tt 文件。
*.tt 文件包含极少数生成代码。 相反,它们使用 <#include> 指令来包括共享的模板文件。 可在 \Program Files\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\DSL SDK\DSL Designer\11.0\TextTemplates 中找到共享的文件
在将你自己的程序代码添加到 DSL 解决方案时,请将它添加在“生成的代码”文件夹之外的单独文件中。 你可能希望创建 Custom Code 文件夹。 (在向自定义文件夹添加新代码文件时,请记住在初始代码主干中更正命名空间。)
强烈建议你不要直接编辑生成的代码,因为当重新生成解决方案时你的编辑将会丢失。 相反,若要自定义 DSL,请执行以下操作:
调整 DSL 定义中的多个参数。
在单独的代码文件中编写分部类,以重写在生成的类中定义的或由生成的类继承的方法。 在某些情况下,为了能够重写生成的方法,你必须在 DSL 定义中设置类的**“生成双派生”**选项。
将 DSL 定义中导致生成的代码的选项设置为向你自己的代码提供“hook”。
例如,如果你设置域类的**“具有自定义构造函数”**选项,然后生成解决方案,则将看到错误消息。 在双击其中一个错误消息时,你将在生成的代码中看到注释,阐释了你的自定义代码应提供的内容。
编写你自己的文本模板以生成特定于应用程序的代码。 可使用包含文件来共享许多项目通用的模板的各个部分,并可创建 Visual Studio 项目模板来设置使用你自己的文件结构初始化的项目。
DSL 中生成的文件
以下生成的文件显示在 Dsl 项目中。
文件名 |
描述 |
---|---|
YourDslSchema.xsd |
包含 DSL 实例的文件的架构。 该文件将复制到编译 (bin) 目录。 在安装 DSL 时,可将此文件复制到 \Program Files\Microsoft Visual Studio 11.0\Xml\Schemas,以便可以验证模型文件。 有关详细信息,请参阅部署域特定语言解决方案。 如果通过在 DSL 资源管理器中设置选项来自定义序列化,则该架构将进行相应的更改。 但是,如果编写自己的序列化代码,则此文件可能不再表示实际架构。 有关详细信息,请参阅自定义文件存储和 XML 序列化。 |
ConnectionBuilders.cs |
连接生成器是用于创建关系的类。 它是位于连接工具后面的代码。 此文件包含一对用于每个连接工具的类。 它们的名称派生自域关系和连接工具的名称:RelationshipBuilder 和 ConnectorToolConnectAction。 (在组件解决方案示例中,其中一个连接生成器称为 ConnectionBuilder,这是一个巧合,因为域关系名为 Connection。) 关系在 RelationshipBuilder.Connect() 方法中创建。 默认版本将验证源和目标模型元素是否为可接受,然后实例化该关系。 例如: CommentReferencesSubject(sourceAccepted, targetAccepted); 每个生成器类都生成自 DSL 资源管理器的“连接生成器”部分中的节点。 一个 Connect 方法可在一对或多对域类之间创建关系。 每一对都由链接连接指令定义,可在 DSL 资源管理器中的生成器节点下查找该指令。 例如,可以为示例 DSL 中三种类型关系的每一种添加一个连接生成器链接连接指令。 这将向用户提供单独的连接工具。 实例化的关系类型将依赖于由用户选择的源和目标元素的类型。 若要添加链接连接指令,请在 DSL 资源管理器中右键单击生成器。 若要编写在创建特定类型的域关系时运行的自定义代码,请在生成器节点下选择相应的链接连接指令。 在“属性”窗口中,设置“使用自定义连接”。 重新生成解决方案,然后提供代码以更正产生的错误。 若要编写每当用户使用此连接工具时运行的自定义代码,请设置连接生成器的“为自定义”属性。 可提供代码来确定是否允许源元素、是否允许特定的源和目标的组合,以及在进行连接时应对模型进行哪些更新。 例如,仅当连接不会在关系图中创建循环时才可允许连接。 可以在源和目标之间实例化多个相关元素的更复杂模式,而不是单一关系链接。 |
Connectors.cs |
包含连接符的类,它们是通常表示引用关系的关系图元素。 每个类都生成自 DSL 定义中的一个连接符。 每个连接符类都派生自 BinaryLinkShape 若要使颜色和某些其他样式功能在运行时可变,请右键单击 DSL 定义关系图上的类并指向“公开添加”。 若要使其他样式功能在运行时可变,请参阅示例 TextField 和 ShapeElement。 |
Diagram.cs |
包含可定义关系图的类。 它派生自 Diagram。 若要使颜色和某些其他样式功能在运行时可变,请右键单击 DSL 定义关系图上的类并指向“公开添加”。 此外,此文件包含 FixupDiagram 规则,该规则将在新元素添加到模型时响应。 该规则将添加新的形状并将该形状链接到模型元素。 |
DirectiveProcessor.cs |
此指令处理器可帮助用户编写读取 DSL 实例的文本模板。 该指令处理器将加载用于 DSL 的程序集 (DLL),并为命名空间有效地插入 using 语句。 这将允许文本模板中的代码使用已在 DSL 中定义的类和关系。 有关详细信息,请参阅从域特定语言生成代码和创建自定义 T4 文本模板指令处理器。 |
DomainClasses.cs |
已定义的域类的实现,包括抽象类和模型根类。 它们派生自 ModelElement。 每个域类包含:
|
DomainModel.cs |
表示域模型的类。 它派生自 DomainModel。 备注 这与模型的根类不同。 “复制”和“删除”闭包定义在复制或删除一个元素时应包含哪些其他元素。 通过在每个关系的每一侧上设置角色的“传播复制”和“传播删除”属性,可控制此行为。 如果想要动态确定这些值,则可编写代码来重写“闭包”类的方法。 有关详细信息,请参阅如何:程序复制和粘贴行为 - 重定向。 |
DomainModelResx.resx |
它包含了诸如域类和属性的说明、属性名称、工具箱标签、标准错误消息等字符串以及可以显示给用户的其他字符串。 它还包含工具图标和用于图像形状的图像。 此文件将绑定到生成的程序集中,并提供这些资源的默认值。 通过创建包含资源的本地化版本的附属程序集,可对 DSL 进行本地化。 当 DSL 安装在与本地化资源相匹配的区域性时,将使用该版本。 有关详细信息,请参阅部署域特定语言解决方案。 |
DomainRelationships.cs |
模型中的两个元素之间的每个链接都由域关系类的实例表示。 所有关系类都派生自 ElementLink,而后者又派生自 ModelElement。 由于它是 ModelElement,因此关系的实例可以具有属性并且可以是关系的源或目标。 |
HelpKeywordHelper.cs |
提供当用户按 F1 时使用的函数。 |
MultiplicityValidation.cs |
在你在其中指定重数为 1..1 或 1..* 的关系角色中,应警告用户至少需要一个关系实例。 此文件提供实现这些警告的验证约束。 指向嵌入父级的 1..1 链接未进行验证。 为了执行这些约束,你必须在 DSL 资源管理器的“编辑器\验证”节点中设置“使用...”选项之一。 有关详细信息,请参阅域特定语言中的验证。 |
PropertiesGrid.cs |
此文件仅在你已将自定义类型描述符附加到域属性时才包含代码。 有关详细信息,请参阅自定义“属性”窗口。 |
SerializationHelper.cs |
|
Serializer.cs |
用于每个域类、关系、形状、连接符、关系图和模型的序列化程序类。 这些类的很多功能都可以由 DSL 资源管理器中的“Xml 序列化行为”下的设置控制。 |
Shapes.cs |
用于 DSL 定义中的每个形状类的类。 形状派生自 NodeShape。 有关详细信息,请参阅自定义文件存储和 XML 序列化。 若要使用分部类中自己的方法来重写生成的方法,请为 DSL 定义中的连接符设置“生成双派生”。 若要使用自己的代码替换构造函数,请设置“具有自定义构造函数”。 若要使颜色和某些其他样式功能在运行时可变,请右键单击 DSL 定义关系图上的类并指向“公开添加”。 若要使其他样式功能在运行时可变,请参阅示例 TextField 和 ShapeElement |
ToolboxHelper.cs |
通过将元素组原型安装到元素工具中来设置工具箱。 当用户运行该工具时,这些原型的副本将与目标元素合并。 可以重写 CreateElementPrototype() 来定义用于创建一组多个对象的工具箱项。 例如,你可以定义某个项来表示具有子组件的对象。 更改代码后,重置 Visual Studio 的实验实例来清除工具箱缓存。 |
DslPackage 项目中生成的文件
DslPackage 将 DSL 模型耦合到 Visual Studio shell,从而管理窗口、工具箱和菜单命令。 大多数类都是双派生的,以便你可以重写它们的任何方法。
文件名 |
描述 |
---|---|
CommandSet.cs |
在关系图上可见的上下文菜单命令。 可以改写此集或向其添加项。 此文件包含命令的代码。 菜单上的命令的位置由 Commands.vsct 文件确定。 有关详细信息,请参阅编写用户命令和操作。 |
Constants.cs |
GUID。 |
DocData.cs |
YourDslDocData 可管理将模型加载并保存到文件的操作,并创建“存储”实例。 例如,如果想要将 DSL 保存在数据库而不是文件中,则可以重写 Load 和 Save 方法。 |
DocView.cs |
YourDslDocView 可管理将在其中显示关系图的窗口。 例如,可以将关系图嵌入在 Windows 窗体内: 将用户控件文件添加到 DslPackage 项目。 添加可在其中显示关系图的面板。 添加按钮和其他控件。 在窗体的代码视图中,添加以下代码,从而调整名称以适应你的 DSL:
|
EditorFactory.cs |
实例化 DocData 和 DocView。 它满足 Visual Studio 用于在 DSL 程序包启动时打开编辑器的标准接口。 将在 Package.cs 的 ProvideEditorFactory 特性中引用它。 |
GeneratedVSCT.vsct |
查找菜单(例如关系图上下文菜单、“编辑”菜单等等)上的标准菜单命令。 命令的代码是 CommandSet.cs。 可以重定位或修改标准命令,并可以添加自己的命令。 有关详细信息,请参阅编写用户命令和操作。 |
ModelExplorer.cs |
为 DSL 定义模型资源管理器。 这是用户将在关系图旁边看到的模型的树视图。 例如,可以重写 InsertTreeView() 来更改元素在模型资源管理器中的显示顺序。 如果想要使模型资源管理器中的选择与关系图选择保持同步,可使用以下代码:
|
ModelExplorerToolWindow.cs |
定义将在其中显示模型资源管理器的窗口。 处理资源管理器中的项的选择。 |
Package.cs |
此文件定义 DSL 集成到 Visual Studio 中的方式。 程序包类上的特性将 DSL 注册为具有文件扩展名的文件的处理程序、定义其工具箱以及定义打开新窗口的方式。 当第一个 DSL 加载到 Visual Studio 实例中时,将调用一次 Initialize() 方法。 |
Source.extension.vsixmanifest |
若要自定义此文件,请编辑 .tt 文件。 警告 如果编辑 .tt 文件来包括资源(例如图标或图像),请确保该资源包括在 VSIX 生成中。在“解决方案资源管理器”中,选择该文件并确保“包含在 VSIX 中”属性为 True。 此文件控制将 DSL 打包到 Visual Studio 集成扩展 (VSIX) 中的方式。 有关详细信息,请参阅部署域特定语言解决方案。 |