如果编写读取的文本模板中包含的设计 Visual Studio ModelBus 引用,则可能要解析对访问目标架构。在这种情况下,必须满足文本模板和引用的域特定语言 (DSLs):
DSL 是目标的引用必须为从文本模板访问配置的 ModelBus 适配器。除了标准 ModelBus 适配器外,如果您还可以从访问其他代码的 DSL,重新配置的适配器需要。
适配器经理必须从 VsTextTemplatingModelingAdapterManager 继承,且必须具有属性 [HostSpecific(HostName)]。
模板必须从 ModelBusEnabledTextTransformation继承。
![]() |
---|
如果要读取不包含的 DSL 模型 ModelBus 引用,可以在 DSL 项目生成的指令处理器。有关更多信息,请参见 从文本模板访问模型。 |
有关文本模板的更多信息,请参见使用 T4 文本模板生成设计时代码。
创建访问受模型总线适配器从文本模板
若要解决 ModelBus 引用在文本模板中,目标 DSL 必须具有兼容的适配器。文本模板在从 Visual Studio 的单独的 AppDomain 执行文档编辑器,并适配器必须加载该模型而非访问它通过预置。
创建与文本模板兼容的 ModelBus 适配器
如果目标 DSL 解决方案没有一个 ModelBusAdapter 项目,使用 Modelbus 扩展向导,请创建一:
,如果尚未执行此操作,请下载并安装 Visual Studio ModelBus 扩展。有关更多信息,请参见 Visualization and Modeling SDK。
打开 DSL 定义文件。右击该设计图面然后单击 启用 Modelbus。
在对话框中,选择 我希望显示此 DSL 在 ModelBus。可以选择两个选项,如果希望此 DSL 显示其设计,并使用对其他 DSL。
单击**“确定”**。一个新项 “ModelBusAdapter”添加到 DSL 解决方案。
单击 转换所有模板。
重新生成解决方案。
如果要访问 DSL 从文本模板和其他代码,例如命令,请重复 ModelBusAdapter 项目:
在 Windows 资源管理器中,复制和粘贴包含 ModelBusAdapter.csproj的文件夹。
给项目文件重命名为 (例如,若要 T4ModelBusAdapter.csproj)。
在 解决方案资源管理器,右击解决方案节点,指向 添加,然后单击 现有项目。找到新适配器项目, T4ModelBusAdapter.csproj。
在新项目中每 *.tt 文件,请更改命名空间。
右击 " 解决方案资源管理器的新项并单击属性。在属性编辑器,请更改生成的程序集和默认命名空间的名称。
在 DslPackage 项目中,添加对新适配器项目,使其具有对两个适配器。
在 DslPackage \ source.extension.tt,添加对新适配器项的一行。
<MefComponent>|T4ModelBusAdapter|</MefComponent>
转换所有模板 和重新生成解决方案。编译错误不应发生。
在新适配器项目中,添加对以下程序集的引用:
Microsoft.VisualStudio.TextTemplating.11.0
Microsoft.VisualStudio.TextTemplating.Modeling.11.0
在 AdapterManager.tt:
更改 AdapterManagerBase 的声明,以便它从 VsTextTemplatingModelingAdapterManager继承。
public partial class <#= dslName =>AdapterManagerBase :
Microsoft.VisualStudio.TextTemplating.Modeling.VsTextTemplatingModelingAdapterManager { ...
在文件末尾附近的,请替换 HostSpecific 特性在 AdapterManager 该类之前。移除以下行:
[DslIntegration::HostSpecific(DslIntegrationShell::VsModelingAdapterManager.HostName)]
插入下面的行:
[Microsoft.VisualStudio.Modeling.Integration.HostSpecific(HostName)]
此属性筛选可用适配器集,当 modelbus 使用者搜索适配器时。
转换所有模板 和重新生成解决方案。编译错误不应发生。
编写能解析 ModelBus 的文本模板引用
通常,可以读取并生成从 “源” DSL 的文件的模板开始。此模板在源 DSL 项目生成读取源模型文件提供一种在 从文本模板访问模型中描述的指令。但是,源 DSL 包含 ModelBus 对 “目标” DSL。因此要使模板代码引用解析和访问目标 DSL。因此必须执行以下步骤来满足模板:
更改模板的基类。 ModelBusEnabledTextTransformation。
包括 hostspecific="true" 在模板指令。
添加程序集引用到目标 DSL 及其适配器和启用 ModelBus。
您不需要作为目标 DSL 的一部分,生成的指令。
<#@ template debug="true" hostspecific="true" language="C#"
inherits="Microsoft.VisualStudio.TextTemplating.Modeling.ModelBusEnabledTextTransformation" #>
<#@ SourceDsl processor="SourceDslDirectiveProcessor" requires="fileName='Sample.source'" #>
<#@ output extension=".txt" #>
<#@ assembly name = "Microsoft.VisualStudio.Modeling.Sdk.Integration.11.0" #>
<#@ assembly name = "Company.TargetDsl.Dsl.dll" #>
<#@ assembly name = "Company.TargetDsl.T4ModelBusAdapter.dll" #>
<#@ assembly name = "System.Core" #>
<#@ import namespace="Microsoft.VisualStudio.Modeling.Integration" #>
<#@ import namespace="Company.TargetDsl" #>
<#@ import namespace="Company.TargetDsl.T4ModelBusAdapters" #>
<#@ import namespace="System.Linq" #>
<#
SourceModelRoot source = this.ModelRoot; // Usual access to source model.
// In the source DSL Definition, the root element has a model reference:
using (TargetAdapter adapter = this.ModelBus.CreateAdapter(source.ModelReference) as TargetAdapter)
{if (adapter != null)
{
// Get the root of the target model:
TargetRoot target = adapter.ModelRoot;
// The source DSL Definition has a class "SourceElement" embedded under the root.
// (Let’s assume they’re all in the same model file):
foreach (SourceElement sourceElement in source.Elements)
{
// In the source DSL Definition, each SourceElement has a MBR property:
ModelBusReference elementReference = sourceElement.ReferenceToTarget;
// Resolve the target model element:
TargetElement element = adapter.ResolveElementReference<TargetElement>(elementReference);
#>
The source <#= sourceElement.Name #> is linked to: <#= element.Name #> in target model: <#= target.Name #>.
<#
}
}}
// Other useful code: this.Host.ResolvePath(filename) gets an absolute filename
// from a path that is relative to the text template.
#>
当此文本模板时, SourceDsl 指令加载文件 Sample.source。模板从 this.ModelRoot启动可以访问该模型的元素,。代码可以使用该 DSL 域类和属性。
另外,模板可能的解决 ModelBus 引用。如果引用指向目标架构,程序集指令允许字段类别和该模型的 DSL 属性的代码使用。
如果不使用由 DSL 项目生成的指令,还应包括以下内容。
<#@ assembly name = "Microsoft.VisualStudio.Modeling.Sdk.11.0" #> <#@ assembly name = "Microsoft.VisualStudio.TextTemplating.Modeling.11.0" #>
使用 this.ModelBus 访问 ModelBus 的访问。
演练:测试使用 ModelBus 的文本模板
在本演练中,请执行以下步骤:
构造两个 DSL。一个 DSL, 使用者,可以引用另一个 DSL 的一个 ModelBusReference 属性,提供程序。
创建两个 ModelBus 适配器在提供程序:一个从文本模板访问,其他泛型的代码。
创建 DSL 的实例模型在一个测试项目。
将一个模型中的某个字段的特性指向另一个模型。
编写打开模型点的双击处理程序。
编写可加载第一个模型,按照对另一个模型和读取另一个模型的文本模板。
构造到 ModelBus 是可访问的 DSL
创建新的 DSL 解决方案。对于此示例,选择任务流解决方案模板。设置语言名称。 MBProvider 和文件扩展名设置为 “.provide”。
在 DSL 定义关系图,右击不位于顶部附近关系图的空白部分,然后单击 启用 Modelbus。
- 如果看不到 启用 Modelbus,您必须下载和安装 VMSDK ModelBus 扩展。查找它在 VMSDK 站点: Visualization and Modeling SDK.
在 启用 Modelbus 对话框中,选择 " 显示此 DSL 在 ModelBus,然后单击 好。
新项目, ModelBusAdapter,即添加到解决方案。
您现在可以从文本模板访问通过 ModelBus 的一个 DSL。在命令、事件处理程序或规则代码对它可以解析,在模型文件编辑的 AppDomain 中运行。但是,在中,在编辑时,在单独的 AppDomain 中运行的文本模板和不可访问模型。如果要访问 ModelBus 对从文本模板,则此 DSL 必须具有单独 ModelBusAdapter。
创建为文本模板配置的 ModelBus 适配器
在 Windows 资源管理器中,复制和粘贴包含 ModelBusAdapter.csproj 的文件夹。
将文件夹命名为 T4ModelBusAdapter。
向项目文件 T4ModelBusAdapter.csproj 重命名。
在解决方案资源管理器中,添加 T4ModelBusAdapter 到 MBProvider 解决方案。右击解决方案节点,指向 添加,然后单击 现有项目。
右击 T4ModelBusAdapter 项目节点然后单击属性。在项目属性 " 窗口中,将 程序集名称 和 默认命名空间 到 Company.MBProvider.T4ModelBusAdapters。
在 T4ModelBusAdapter 的每 *.tt 文件,请插入 “T4”到命名空间中的最后一部分,因此,行类似于以下内容。
namespace <#= CodeGenerationUtilities.GetPackageNamespace(this.Dsl) #>.T4ModelBusAdapters
在 DslPackage 项目中,添加对项目的项目引用。 T4ModelBusAdapter。
在 DslPackage \ source.extension.tt,添加下面的行。 <Content>下。
<MefComponent>|T4ModelBusAdapter|</MefComponent>
在 T4ModelBusAdapter 项目中,添加对: Microsoft.VisualStudio.TextTemplating.Modeling.11.0
打开 T4ModelBusAdapter \AdapterManager .tt:
更改 AdapterManagerBase 基类。 VsTextTemplatingModelingAdapterManager。此文件的部分现在类似于以下内容。
namespace <#= CodeGenerationUtilities.GetPackageNamespace(this.Dsl) #>.T4ModelBusAdapters { /// <summary> /// Adapter manager base class (double derived pattern) for the <#= dslName #> Designer /// </summary> public partial class <#= dslName #>AdapterManagerBase : Microsoft.VisualStudio.TextTemplating.Modeling.VsTextTemplatingModelingAdapterManager {
在文件末尾附近的,在类 AdapterManager 前面的以下附加属性。
[Microsoft.VisualStudio.Modeling.Integration.HostSpecific(HostName)]
则结果将类似于以下内容。
/// <summary> /// ModelBus modeling adapter manager for a <#= dslName #>Adapter model adapter /// </summary> [Mef::Export(typeof(DslIntegration::ModelBusAdapterManager))] [Mef::ExportMetadata(DslIntegration::CompositionAttributes.AdapterIdKey,<#= dslName #>Adapter.AdapterId)] [DslIntegration::HostSpecific(DslIntegrationShell::VsModelingAdapterManager.HostName)] [Microsoft.VisualStudio.Modeling.Integration.HostSpecific(HostName)] public partial class <#= dslName #>AdapterManager : <#= dslName #>AdapterManagerBase { }
单击 转换所有模板 在标题栏解决方案资源管理器中。
重新生成解决方案。单击 F5。
验证 DSL 工作项按 F5 旁边。在实验项目中,打开 Sample.provider。关闭 Visual Studio 的实验实例。
ModelBus 引用了此 DSL 现在即可解决在文本模板并在普通的代码。
构造使用 ModelBus 的一个 DSL 引用字段的特性
使用最小的语言解决方案模板,创建一个新的 DSL。命名该语言 MBConsumer 并将文件扩展名设置为 “.consume”。
在 DSL 项目中,添加对 MBProvider DSL 程序集。右击 MBConsumer\Dsl\References 然后单击 添加引用。在 浏览 选项,找到 MBProvider\Dsl\bin\Debug\Company.MBProvider.Dsl.dll
这使您可以创建使用另一个 DSL 的代码。如果要创建对多个 DSL,还添加它们。
在 DSL 定义关系图,请右击关系图然后单击 启用 ModelBus。在对话框中,选择 使此 DSL 使用 ModelBus。
在类 ExampleElement,请在 " 属性 " 窗口中添加一个新字段的属性 MBR,并且,将其类型设置为 ModelBusReference。
右击关系图的字段的特性然后单击 编辑 ModelBusReference 特定属性。在对话框中,选择 一个模型元素。
设置文件对话框筛选器将以下内容。
Provider File|*.provide
在子字符串 “|”是文件选择对话框中的筛选器。使用 *.*,您可以将它允许任意文件
在 模型元素类型 列表中,输入一矿石的名称多个字段类在提供程序 DSL (例如, Company.MBProvider.Task)。它们可以是抽象类。如果保留空白列表,用户可将对所有元素。
关闭对话框并 转换所有模板。
您创建了可能包含对另一个 DSL 的元素的一个 DSL。
创建 ModelBus 引用添加到解决方案中的其他文件
在 MBConsumer 解决方案,请按 CTRL+F5。Visual Studio 的实验实例。 MBConsumer\Debugging 项目打开。
添加 Sample.provide 的复制到 MBConsumer\Debugging 项目。,因为 ModelBus 引用必须引用同一解决方案,的文件这是必需的。
右击调试项目,指向 添加,然后单击 现有项目。
在 添加项目 对话框中,将筛选器将 所有文件 (*.*)。
导航到 MBProvider\Debugging\Sample.provide 然后单击 添加。
打开 Sample.consume。
单击一个示例形状,然后在 " 属性 " 窗口中,在 MBR 单击属性 [...] 。在对话框中,单击 浏览 并选择 Sample.provide。在元素窗口中,展开该类型任务并选择一个元素。
保存该文件。
(不要关闭 Visual Studio的实验实例。)
您创建了一个包含 ModelBus 对另一个模型中的元素的模型。
解决 ModelBus 对文本模板
在 Visual Studio的实验实例中,打开示例文本模板文件。如下所示设置其内容。
<#@ template debug="true" hostspecific="true" language="C#" inherits="Microsoft.VisualStudio.TextTemplating.Modeling.ModelBusEnabledTextTransformation" #> <#@ MBConsumer processor="MBConsumerDirectiveProcessor" requires="fileName='Sample.consume'" #> <#@ output extension=".txt" #> <#@ assembly name = "Microsoft.VisualStudio.Modeling.Sdk.Integration.11.0" #> <#@ assembly name = "Company.MBProvider.Dsl.dll" #> <#@ import namespace="Microsoft.VisualStudio.Modeling.Integration" #> <#@ import namespace="Company.MBProvider" #> <# // Property provided by the Consumer directive processor: ExampleModel consumerModel = this.ExampleModel; // Iterate through Consumer model, listing the elements: foreach (ExampleElement element in consumerModel.Elements) { #> <#= element.Name #> <# if (element.MBR != null) using (ModelBusAdapter adapter = this.ModelBus.CreateAdapter(element.MBR)) { // If we allowed multiple types or DSLs in the MBR, discover type here. Task task = adapter.ResolveElementReference<Task>(element.MBR); #> <#= element.Name #> is linked to Task: <#= task==null ? "(null)" : task.Name #> <# } } #>
请注意以下内容:
必须设置 template 指令的 hostSpecific 和 inherits 属性。
使用者模型来访问以常规方式通过在该 DSL 生成的指令处理器。
程序集和导入指令必须能够访问 ModelBus 和提供程序 DSL 的类型。
如果您知道许多 MBR 与同一模型链接,调用 CreateAdapter 只有一个最好。
保存模板。验证生成的文本文件类似于以下内容。
ExampleElement1 ExampleElement2 ExampleElement2 is linked to Task: Task2
解决 ModelBus 引用在笔势处理程序
,则运行,结束 Visual Studio的实验实例。
添加一个名为 MBConsumer \Dsl\Custom .cs 并将其设置为以下内容的文件。
namespace Company.MB2Consume { using Microsoft.VisualStudio.Modeling.Integration; using Company.MB3Provider; public partial class ExampleShape { public override void OnDoubleClick(Microsoft.VisualStudio.Modeling.Diagrams.DiagramPointEventArgs e) { base.OnDoubleClick(e); ExampleElement element = this.ModelElement as ExampleElement; if (element.MBR != null) { IModelBus modelbus = this.Store.GetService(typeof(SModelBus)) as IModelBus; using (ModelBusAdapter adapter = modelbus.CreateAdapter(element.MBR)) { Task task = adapter.ResolveElementReference<Task>(element.MBR); // Open a window on this model: ModelBusView view = adapter.GetDefaultView(); view.Show(); view.SetSelection(element.MBR); } } } } }
按 Ctrl+F5。
在 Visual Studio的实验实例中,打开 Debugging\Sample.consume。
双击一个形状。
如果将该元素的 MBR,被引用的方式打开,并被引用的元素中选择。