VS2013和VS2015中的T4文本转换

时间:2015-08-06 05:59:18

标签: visual-studio-2013 visual-studio-2015 t4

我们公司拥有严重依赖T4的遗留系统,而构建它的员工已经不复存在。它对我们来说运行良好,但最近一些开发人员升级到VS2015。 T4转换停止为它们工作(错误类似于下面报告的)。虽然有Microsoft.VisualStudio.TextTemplating.12.0.dll的引用,但它看了一下。他们改变了对'14'的引用,并且都为他们工作。但是,VS2013上其他开发人员共享的同一项目不再使用错误:

  

编译转换:类型   'Microsoft.VisualStudio.TextTemplating.TextTransformation'已定义   在未引用的程序集中。您必须添加引用   程序集'Microsoft.VisualStudio.TextTemplating.14.0,   Version = 14.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a'。

您是否能够在VS2013和VS2015中打开的同一项目上运行T4?另一方面,有一个依赖程序集,旧员工使得所有TextTransformation都派生自(它还提供了* .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个文件,该项目包含在应用了文本转换的项目的解决方案中。

  1. 我们有一个帮助器Extensibility.CodeGeneration.dll(这也引用了Microsoft.VisualStudio.TextTemplating.N.dll文件),它有几个静态助手以及从Microsoft派生的基类.VisualStudio.TextTemplating.TextTransformation

  2. 包含所有* .tt文件的每个 .tt文件都使用我们的帮助器dll中的静态方法。它还引用了所有相同的Microsoft.VisualStudio。 dlls。

  3. 每个 * .tt文件中,我们有类似这样的东西,其中AreaTemplate是* .tt文件本身定义的类,并且派生自Microsoft.VisualStudio.TextTemplating .TextTransformation或我们的helper dll中的一个公开的基类。

    var template = new AreaTemplate {Settings = settings,Area = area,Layouts = layouts}; 写(template.TransformText());

  4. 我在评论中询问我是如何获得/使用'主持人'的。在搜索代码时,我们有一些常见的场景(都在helper dll中完成)。在每个实例中,主机的类型为ITextTemplatingEngineHost

  5. 案例1:

    var dte = (EnvDTE.DTE)( (IServiceProvider)host ).GetService( typeof( EnvDTE.DTE ) );
    

    案例2:

    var hostServiceProvider = (IServiceProvider)host;
    

    鉴于上面的#3,我认为由于TextTransformation类的使用/公开,我必须引用Microsoft.TextTemplating dll(而不仅仅是Interfaces dll)。

    另外,如果我将'Helper'和'Templates'项目中的引用更改为12.0 ...在vs2015中,我收到错误'你必须添加对12.0的引用'...我在那里引用了两个适用(在我看来)项目...不知道为什么VS告诉我添加它。我尝试使用

    在* .tt文件中添加显式引用
    <#@ assembly Name="$(ProjectDir)..\..\Assemblies\Microsoft.VisualStudio.TextTemplating.12.0.dll" #>
    

    但后来我收到了错误

      

    类型'Microsoft.VisualStudio.TextTemplating.TextTransformation'   存在于两者中   'C:\ BTR \来源\组件\ Microsoft.VisualStudio.TextTemplating.12.0.dll'   和   'C:\的Windows \ Microsoft.NET \组件\ GAC_MSIL \ Microsoft.VisualStudio.TextTemplating.14.0 \ v4.0_14.0.0.0__b03f5f7f11d50a3a \ Microsoft.VisualStudio.TextTemplating.14.0.dll'

    几乎就像已经内置到VS中的最新Texttemplating的隐藏/隐式引用?

    不确定我们的设置是否是实现我们原始目标的更复杂的方式,但我认为如果我们以不正确的方式进行操作,我将无法解除它并进行更改。

    鉴于我们的设置让我知道你是否认为我被卡住了。我试图弄清楚MSBuild中的“条件”,以帮助支持Visual Studio,但无法成功。

    提前致谢。

3 个答案:

答案 0 :(得分:4)

尝试更改&#34; Microsoft.VisualStudio.TextTemplating.12.0.dll&#34;的引用。到&#34; Microsoft.VisualStudio.TextTemplating.Interfaces.12.0.dll&#34;。每个新版本的Visual Studio服务都将有一个新的实现程序集,它将实现以前的版本接口。要保持向后兼容性,您应该只引用接口程序集而不是实现程序集。如果模板引用了不在界面中的任何内容,则可能必须更改模板。

<强>更新

哇,所以你有一个非常复杂的设置,我不知道你是否能够在两个版本中使用它而不像你那样改变代码。

我认为主要问题出在你的助手类中,在#3中,你说AreaTemplate类派生自TextTransformation。 TextTransformation位于实现dll中,因此它将存在于每个版本的visual studio中。如果你帮助dll遵守从2013年引用它然后你在2015年使用该DLL将无法正常工作。

当转换T4模板时,文件中的文本被解析为一个类,该类被加载到一个app域(与一个visual studio正在运行)并且类的TransformText方法是调用。由于您的模板引用了您的帮助程序类,因此辅助程序程序集将被加载到新的应用程序域中,而新的应用程序域也会尝试在其中加载TextTemplating 12,因为您正在使用VS,因此应用程序域将无法解析12引用2015年。

在另一个方向,当您从2015年引用文本模板14并尝试在VS 2013中使用它时您将遇到相同的问题,应用程序域将无法找到TextTemplating 14,因为您在VS 2013和14中dll不存在。

在最后一个场景中,当您进入VS 2015并在tt文件中添加指向TextTemplating 12的链接时,它失败了,因为为运行模板而创建的应用程序域已经加载了TextTemplating 14 dll然后您还告诉它加载TextTemplating 12 dll。当我谈到VS向后兼容性时,这回到我在评论中的帖子,TextTemplating 12和14在同一名称空间中具有相同的TextTransformation类,并且运行时无法加载它们,因此您得到了该错误。

你可以尝试几件事:

1)将TextTemplating 12 dll放在VS 2015计算机上的GAC中。从理论上讲,这将让T4 AppDomain加载TextTemplating的两个副本,然后VS 2015将能够使用14版本,而你的tt文件和helper dll使用12版本。让VS 2013机器保持不变。

2)与1相同,但相反,将项目设置为目标2015并引用14 dll然后在vs 2013计算机GAC 14 dll上,不确定这是否可行,因为14 dll可能有其他依赖项在较新的vs组装。

3)在vs 2015计算机上找到了一种为T4 App Domain进行绑定重定向的方法,以便将查看TextTemplating 12的调用解析为TextTemplating 14.通常,绑定重定向在app / web.config文件中完成但不确定如何为T4执行这些操作,可能需要查看代码并查看应用程序域的创建和加载方式。

答案 1 :(得分:1)

我遇到了同样的问题,我认为我有一个解决方案,它有效 - 使用 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

似乎工作。

答案 2 :(得分:0)

我们有一个非常类似的场景,只是有点复杂,因为我们的T4模板依赖于几个DSL-Tools软件包。

我已经做了一些测试,实际上这个问题的解决方案是删除对Microsoft.VisualStudio.TextTemplating.12.0的任何引用并保留对Interfaces程序集的引用。正如弗兰克指出的那样。这将使项目和模板与Visual Studio 2013和2015兼容。

不幸的是,这在我们的场景中没有帮助,因为DSL工具项目需要引用Microsoft.VisualStudio.TextTemplating.12.0Microsoft.VisualStudio.TextTemplating.14.0,因为DirectiveProcessor.tt模板会生成一个派生自RequiresProvidesDirectiveProcessor的类,一个驻留在其中一个程序集中的抽象类(取决于您希望编译DSL-tools项目的Visual Studio版本)。 我认为这是使用更高的Visual Studio版本打开它们时升级DSL工具项目的原因之一......但这很痛苦,因为它迫使像我们这样的大型团队同时升级Visual Studio。