VS2013 和 VS2015 中的 T4 文本转换
T4 Text Transformations in VS2013 and VS2015
我们公司有严重依赖 T4 的遗留系统,而设计它的员工已经不在了。 运行 对我们来说很好,但是最近一些开发人员升级到了 VS2015。 T4 转换停止为它们工作(错误与下面报告的类似)。它看起来虽然有对 Microsoft.VisualStudio.TextTemplating.12.0.dll
的引用。他们将引用更改为“14”,并且都为他们工作。但是,其他开发人员在 VS2013 上共享的同一个项目不再工作并出现错误:
Compiling transformation: The type
'Microsoft.VisualStudio.TextTemplating.TextTransformation' is defined
in an assembly that is not referenced. You must add a reference to
assembly 'Microsoft.VisualStudio.TextTemplating.14.0,
Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
您能否在 VS2013 和 VS2015 中打开的同一项目上 运行 T4?一方面,有一个依赖程序集,老员工制作了所有 TextTransformations 派生自(它还提供了在 *.tt 文件中使用的助手)。不幸的是,它使用了一个仅存在于 Microsoft.VisualStudio.TextTemplating.Interfaces.10.0.dll
中的接口,因此旧的参考资料被拖来拖去。不确定这是否有贡献。但基本上这是底线:
当所有开发人员都使用 VS2013 时,一切正常,参考文献为:
Microsoft.VisualStudio.TextTemplating.12.0.dll
Microsoft.VisualStudio.TextTemplating.Interfaces.10.0.dll
Microsoft.VisualStudio.TextTemplating.VSHost.12.0.dll
然后当一些人转到 vs2015 时,让它工作的唯一方法是用 14.0 更改 12.0* dll,但随后 vs2013 开发人员停止工作。
更新
我可能没有阐明我们的完整设置。我们在一个单独的项目中有 20-30 个 *.tt 文件,该项目包含在将对其应用文本转换的项目的解决方案中。
我们有一个助手 Extensibility.CodeGeneration.dll(这也引用了 Microsoft.VisualStudio.TextTemplating.N.dll 文件),它有几个静态助手和派生自 [=] 的基础 classes 90=].
包含所有 *.tt 文件的 'templates' 项目,每个 .tt 文件使用我们的静态方法帮助程序 dll。它还引用了所有相同的 Microsoft.VisualStudio. dlls.
在每个 *.tt 文件中,我们有一些看起来像这样的东西,其中 AreaTemplate 是在 *.tt 文件中定义的 class文件本身,并且派生自 Microsoft.VisualStudio.TextTemplating.TextTransformation 或我们的助手 dll 中公开的基础 class 之一。
var template = new AreaTemplate { Settings = settings, Area = area, Layouts = layouts };
写( template.TransformText() );
有人在评论中问我如何obtained/used一个'host'。在搜索代码时,我们有几个常见的场景(都在 helper dll 中完成)。在每个实例中,主机都是 ITextTemplatingEngineHost
.
类型
案例 1:
var dte = (EnvDTE.DTE)( (IServiceProvider)host ).GetService( typeof( EnvDTE.DTE ) );
案例 2:
var hostServiceProvider = (IServiceProvider)host;
鉴于上面的#3,我认为我必须引用Microsoft.TextTemplating dll(而不仅仅是接口dll),因为use/exposing TextTransformation class.
此外,如果我将 'Helper' 和 'Templates' 项目中的引用更改为 12.0...在 vs2015 中,我会收到关于 'you must add reference to 12.0' 的错误...我有引用在两个适用的(在我眼中)项目中……不确定为什么 VS 告诉我添加它。我尝试使用
在 *.tt 文件中添加显式引用
<#@ assembly Name="$(ProjectDir)..\..\Assemblies\Microsoft.VisualStudio.TextTemplating.12.0.dll" #>
但是我得到了错误
The type 'Microsoft.VisualStudio.TextTemplating.TextTransformation'
exists in both
'c:\BTR\Source\Assemblies\Microsoft.VisualStudio.TextTemplating.12.0.dll'
and
'c:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.VisualStudio.TextTemplating.14.0\v4.0_14.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.TextTemplating.14.0.dll'
几乎就像有一个 hidden/implicit 对已经内置到 VS 中的最新 Texttemplating 的引用?
不确定我们的设置是否是实现我们最初目标的更复杂的方法,但我认为如果我们以不正确的方式进行设置,我将无法解除它并进行更改。
根据我们的设置让我知道您是否认为我被卡住了。我试图找出 MSBuild 中的 'conditions' 以帮助支持两个 Visual Studio,但未能成功。
提前致谢。
尝试将引用从 "Microsoft.VisualStudio.TextTemplating.12.0.dll" 更改为 "Microsoft.VisualStudio.TextTemplating.Interfaces.12.0.dll"。 Visual Studio 服务的每个新版本都将有一个新的实现程序集来实现以前版本的接口。为了保持向后兼容性,您应该只引用接口程序集而不是实现程序集。如果模板引用了界面中没有的任何内容,您可能必须更改模板。
已更新
哇,所以你的设置相当复杂,我不知道你是否可以在两个版本中使用它而无需像你那样更改代码。
我认为主要问题出在您的助手 class 中,您在#3 中说 AreaTemplate class 派生自 TextTransformation。 TextTransformation 在实现 dll 中,因此它将存在于 visual studio 的每个版本中。如果您的 helper dll 从 2013 年开始引用它,然后您在 2015 年使用该 dll,它将无法工作。
转换T4模板时,文件中的文本被解析为class,class被加载到应用程序域(与visual studio分开的是运行ning in) 并调用 class 的 TransformText 方法。由于您的模板引用了您的助手 class,助手程序集将被加载到新的应用程序域中,这又会尝试在其中加载 TextTemplating 12,应用程序域将无法解析 12 引用,因为您正在使用 VS 2015。
另一方面,当您引用 2015 年的文本模板 14 并尝试在 VS 2013 中使用它时,您将遇到同样的问题,应用程序域将无法找到 TextTemplating 14,因为您在 VS 2013 中并且14 dll 不存在。
在最后一个场景中,当您在 VS 2015 中并在您的 tt 文件中向 TextTemplating 12 添加 link 时,它失败了,因为为 运行 模板创建的应用程序域已经加载TextTemplating 14 dll 然后你还告诉它加载 TextTemplating 12 dll。这可以追溯到我在评论中谈到 VS 向后兼容性时的帖子,TextTemplating 12 和 14 在同一命名空间中具有相同的 TextTransformation class,并且 运行time 无法同时加载它们,因此您得到那个错误。
您可以尝试的几件事:
1) 将 TextTemplating 12 dll 放入 VS 2015 机器上的 GAC 中。理论上,这将使 T4 AppDomain 加载 TextTemplating 的两个副本,然后 VS 2015 将能够使用 14 版本,而您的 tt 文件和帮助程序 dll 使用 12 版本。保持 VS 2013 机器不变。
2) 与 1 相同,但相反,将项目设置为目标 2015 并引用 14 dll,然后在 vs 2013 机器上 GAC 14 dll,不确定这是否有效,因为 14 dll 可能有对较新程序集的其他依赖项。
3) 在 vs 2015 机器上找出一种方法来为 T4 应用程序域进行绑定重定向,以便将查找 TextTemplating 12 的调用解析为 TextTemplating 14。通常绑定重定向在 [=36= .config 文件,但不确定如何为 T4 执行它们,可能需要查看代码并查看应用程序域是如何创建和加载的。
我们的场景与您的场景非常相似,只是稍微复杂一点,因为我们的 T4 模板依赖于几个 DSL-Tools 包。
我做了一些测试,实际上这个问题的解决方案是删除对 Microsoft.VisualStudio.TextTemplating.12.0
的任何引用并保留对接口程序集的引用。正如弗兰克所指出的那样。这将使项目和模板与 Visual Studio 2013 和 2015 兼容。
不幸的是,这在我们的场景中没有帮助,因为 DSL-tools 项目需要引用 Microsoft.VisualStudio.TextTemplating.12.0
或 Microsoft.VisualStudio.TextTemplating.14.0
,因为 DirectiveProcessor.tt
模板生成 class派生自 RequiresProvidesDirectiveProcessor
,一个驻留在其中一个程序集中的抽象 class(取决于您希望用来编译 DSL-tools 项目的 Visual Studio 的版本)。
我想这就是为什么 DSL-tools 项目在你用更高的 Visual Studio 版本打开它们时升级的原因之一......但这很痛苦,因为它迫使像我们这样的大型团队升级 Visual Studio 所有同时
我遇到了同样的问题,我想我有一个有效的解决方案 - 使用 VisualStudioVersion msbuild 属性 引用正确版本的程序集。像这样:
<Reference Include="Microsoft.VisualStudio.TextTemplating.$(VisualStudioVersion)">
<HintPath>..\Dependencies\Microsoft.VisualStudio.TextTemplating.$(VisualStudioVersion).dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TextTemplating.Interfaces.10.0">
<HintPath>..\Dependencies\Microsoft.VisualStudio.TextTemplating.Interfaces.10.0.dll</HintPath>
</Reference>
确保 Dependencies 文件夹同时包含 Microsoft.VisualStudio.TextTemplating.12.0.dll 和 Microsoft.VisualStudio.TextTemplating.14.0.dll.
似乎有效。
我们公司有严重依赖 T4 的遗留系统,而设计它的员工已经不在了。 运行 对我们来说很好,但是最近一些开发人员升级到了 VS2015。 T4 转换停止为它们工作(错误与下面报告的类似)。它看起来虽然有对 Microsoft.VisualStudio.TextTemplating.12.0.dll
的引用。他们将引用更改为“14”,并且都为他们工作。但是,其他开发人员在 VS2013 上共享的同一个项目不再工作并出现错误:
Compiling transformation: The type 'Microsoft.VisualStudio.TextTemplating.TextTransformation' is defined in an assembly that is not referenced. You must add a reference to assembly 'Microsoft.VisualStudio.TextTemplating.14.0, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
您能否在 VS2013 和 VS2015 中打开的同一项目上 运行 T4?一方面,有一个依赖程序集,老员工制作了所有 TextTransformations 派生自(它还提供了在 *.tt 文件中使用的助手)。不幸的是,它使用了一个仅存在于 Microsoft.VisualStudio.TextTemplating.Interfaces.10.0.dll
中的接口,因此旧的参考资料被拖来拖去。不确定这是否有贡献。但基本上这是底线:
当所有开发人员都使用 VS2013 时,一切正常,参考文献为:
Microsoft.VisualStudio.TextTemplating.12.0.dll
Microsoft.VisualStudio.TextTemplating.Interfaces.10.0.dll
Microsoft.VisualStudio.TextTemplating.VSHost.12.0.dll
然后当一些人转到 vs2015 时,让它工作的唯一方法是用 14.0 更改 12.0* dll,但随后 vs2013 开发人员停止工作。
更新
我可能没有阐明我们的完整设置。我们在一个单独的项目中有 20-30 个 *.tt 文件,该项目包含在将对其应用文本转换的项目的解决方案中。
我们有一个助手 Extensibility.CodeGeneration.dll(这也引用了 Microsoft.VisualStudio.TextTemplating.N.dll 文件),它有几个静态助手和派生自 [=] 的基础 classes 90=].
包含所有 *.tt 文件的 'templates' 项目,每个 .tt 文件使用我们的静态方法帮助程序 dll。它还引用了所有相同的 Microsoft.VisualStudio. dlls.
在每个 *.tt 文件中,我们有一些看起来像这样的东西,其中 AreaTemplate 是在 *.tt 文件中定义的 class文件本身,并且派生自 Microsoft.VisualStudio.TextTemplating.TextTransformation 或我们的助手 dll 中公开的基础 class 之一。
var template = new AreaTemplate { Settings = settings, Area = area, Layouts = layouts }; 写( template.TransformText() );
有人在评论中问我如何obtained/used一个'host'。在搜索代码时,我们有几个常见的场景(都在 helper dll 中完成)。在每个实例中,主机都是
ITextTemplatingEngineHost
. 类型
案例 1:
var dte = (EnvDTE.DTE)( (IServiceProvider)host ).GetService( typeof( EnvDTE.DTE ) );
案例 2:
var hostServiceProvider = (IServiceProvider)host;
鉴于上面的#3,我认为我必须引用Microsoft.TextTemplating dll(而不仅仅是接口dll),因为use/exposing TextTransformation class.
此外,如果我将 'Helper' 和 'Templates' 项目中的引用更改为 12.0...在 vs2015 中,我会收到关于 'you must add reference to 12.0' 的错误...我有引用在两个适用的(在我眼中)项目中……不确定为什么 VS 告诉我添加它。我尝试使用
在 *.tt 文件中添加显式引用<#@ assembly Name="$(ProjectDir)..\..\Assemblies\Microsoft.VisualStudio.TextTemplating.12.0.dll" #>
但是我得到了错误
The type 'Microsoft.VisualStudio.TextTemplating.TextTransformation' exists in both 'c:\BTR\Source\Assemblies\Microsoft.VisualStudio.TextTemplating.12.0.dll' and 'c:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.VisualStudio.TextTemplating.14.0\v4.0_14.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.TextTemplating.14.0.dll'
几乎就像有一个 hidden/implicit 对已经内置到 VS 中的最新 Texttemplating 的引用?
不确定我们的设置是否是实现我们最初目标的更复杂的方法,但我认为如果我们以不正确的方式进行设置,我将无法解除它并进行更改。
根据我们的设置让我知道您是否认为我被卡住了。我试图找出 MSBuild 中的 'conditions' 以帮助支持两个 Visual Studio,但未能成功。
提前致谢。
尝试将引用从 "Microsoft.VisualStudio.TextTemplating.12.0.dll" 更改为 "Microsoft.VisualStudio.TextTemplating.Interfaces.12.0.dll"。 Visual Studio 服务的每个新版本都将有一个新的实现程序集来实现以前版本的接口。为了保持向后兼容性,您应该只引用接口程序集而不是实现程序集。如果模板引用了界面中没有的任何内容,您可能必须更改模板。
已更新
哇,所以你的设置相当复杂,我不知道你是否可以在两个版本中使用它而无需像你那样更改代码。
我认为主要问题出在您的助手 class 中,您在#3 中说 AreaTemplate class 派生自 TextTransformation。 TextTransformation 在实现 dll 中,因此它将存在于 visual studio 的每个版本中。如果您的 helper dll 从 2013 年开始引用它,然后您在 2015 年使用该 dll,它将无法工作。
转换T4模板时,文件中的文本被解析为class,class被加载到应用程序域(与visual studio分开的是运行ning in) 并调用 class 的 TransformText 方法。由于您的模板引用了您的助手 class,助手程序集将被加载到新的应用程序域中,这又会尝试在其中加载 TextTemplating 12,应用程序域将无法解析 12 引用,因为您正在使用 VS 2015。
另一方面,当您引用 2015 年的文本模板 14 并尝试在 VS 2013 中使用它时,您将遇到同样的问题,应用程序域将无法找到 TextTemplating 14,因为您在 VS 2013 中并且14 dll 不存在。
在最后一个场景中,当您在 VS 2015 中并在您的 tt 文件中向 TextTemplating 12 添加 link 时,它失败了,因为为 运行 模板创建的应用程序域已经加载TextTemplating 14 dll 然后你还告诉它加载 TextTemplating 12 dll。这可以追溯到我在评论中谈到 VS 向后兼容性时的帖子,TextTemplating 12 和 14 在同一命名空间中具有相同的 TextTransformation class,并且 运行time 无法同时加载它们,因此您得到那个错误。
您可以尝试的几件事:
1) 将 TextTemplating 12 dll 放入 VS 2015 机器上的 GAC 中。理论上,这将使 T4 AppDomain 加载 TextTemplating 的两个副本,然后 VS 2015 将能够使用 14 版本,而您的 tt 文件和帮助程序 dll 使用 12 版本。保持 VS 2013 机器不变。
2) 与 1 相同,但相反,将项目设置为目标 2015 并引用 14 dll,然后在 vs 2013 机器上 GAC 14 dll,不确定这是否有效,因为 14 dll 可能有对较新程序集的其他依赖项。
3) 在 vs 2015 机器上找出一种方法来为 T4 应用程序域进行绑定重定向,以便将查找 TextTemplating 12 的调用解析为 TextTemplating 14。通常绑定重定向在 [=36= .config 文件,但不确定如何为 T4 执行它们,可能需要查看代码并查看应用程序域是如何创建和加载的。
我们的场景与您的场景非常相似,只是稍微复杂一点,因为我们的 T4 模板依赖于几个 DSL-Tools 包。
我做了一些测试,实际上这个问题的解决方案是删除对 Microsoft.VisualStudio.TextTemplating.12.0
的任何引用并保留对接口程序集的引用。正如弗兰克所指出的那样。这将使项目和模板与 Visual Studio 2013 和 2015 兼容。
不幸的是,这在我们的场景中没有帮助,因为 DSL-tools 项目需要引用 Microsoft.VisualStudio.TextTemplating.12.0
或 Microsoft.VisualStudio.TextTemplating.14.0
,因为 DirectiveProcessor.tt
模板生成 class派生自 RequiresProvidesDirectiveProcessor
,一个驻留在其中一个程序集中的抽象 class(取决于您希望用来编译 DSL-tools 项目的 Visual Studio 的版本)。
我想这就是为什么 DSL-tools 项目在你用更高的 Visual Studio 版本打开它们时升级的原因之一......但这很痛苦,因为它迫使像我们这样的大型团队升级 Visual Studio 所有同时
我遇到了同样的问题,我想我有一个有效的解决方案 - 使用 VisualStudioVersion msbuild 属性 引用正确版本的程序集。像这样:
<Reference Include="Microsoft.VisualStudio.TextTemplating.$(VisualStudioVersion)">
<HintPath>..\Dependencies\Microsoft.VisualStudio.TextTemplating.$(VisualStudioVersion).dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TextTemplating.Interfaces.10.0">
<HintPath>..\Dependencies\Microsoft.VisualStudio.TextTemplating.Interfaces.10.0.dll</HintPath>
</Reference>
确保 Dependencies 文件夹同时包含 Microsoft.VisualStudio.TextTemplating.12.0.dll 和 Microsoft.VisualStudio.TextTemplating.14.0.dll.
似乎有效。