【问题标题】:Cannot reference dependency assemblies in T4 template when using TransformOnBuild使用 TransformOnBuild 时无法在 T4 模板中引用依赖程序集
【发布时间】:2011-05-04 16:49:36
【问题描述】:

我们正在尝试将 T4 与 Visual Studio 2010 (SP1) 结合使用,为基于我们现有的一些 C# 类的另一种语言构建脚本。我希望得到以下结果:

  1. 模板需要加载我们现有的程序集并使用该程序集中命名空间中的对象。
  2. 转换需要在每台开发机器和构建服务器的每个构建上运行,无需任何额外安装。
  3. (1) 和 (2) 需要协同工作。

(1) 相当简单:

<#@ assembly name="$(TargetDir)RequiredProject.dll" #>
<#@ import namespace="RequiredProject.RequiredNamespace" #>

使用 $(TargetDir) 宏允许我使用完全限定的 UNC 路径引用 dll(根据指令 found here)。

(2) 有点迂回,但我想我已经解决了:我在另一台机器上安装了required text transformation SDKs,并将所需的 .targets 和 .dlls 复制到我的解决方案中的一个文件夹中,然后更新了我的.csproj 文件以引用本地 .targets 文件。

(3) 是我遇到问题的地方。当需要在转换之前构建引用的程序集时,&lt;TransformOnBuild&gt;true&lt;/TransformOnBuild&gt; 属性似乎不能很好地发挥作用。每次我使用引用的程序集在构建上启用转换时,都会收到以下错误:

Compiling transformation: Metadata file '$(TargetDir)RequiredProject.dll' could not be found.

但是,我使用与 (1) 中相同的汇编指令来引用程序集。事实上,直接转到 .tt 模板并保存它仍然会产生预期的输出——它只是在“构建”步骤期间不起作用。我做错了什么,还是有办法确保模板转换发生在它们所依赖的程序集构建之后? (或者,更简单地说,模板转换最后发生?)

【问题讨论】:

标签: c# visual-studio-2010 code-generation t4


【解决方案1】:

很遗憾,msbuild T4 主机还不支持在程序集名称中嵌入宏或 msbuild 变量。

但是,它确实支持 Windows 环境变量“%foo%”,因此虽然这意味着一些机器级设置,但您可以获得跨 IDE 和构建时间转换工作的东西。

【讨论】:

  • 谢谢!那真的很有帮助。我使用自定义任务来设置环境变量并在我的模板中使用它。然而,现在我得到了可怕的“无法复制文件'...dll'”的问题,尽管我使用的是VS 2010 SP1。知道为什么会发生这种情况吗?
  • 我们需要更详细的重现才能有很大的帮助机会 - 它通常意味着从构建中干净地工作。
  • 对于无法复制 dll - 认为您需要使用 volatileassembly 引用,而不是程序集。对于自定义任务 - 您是否介意分享一下您是如何做到的,因为我们在 targetdir 上遇到了同样的问题,并且设置 %envvar% = $targetdir 的简单 p[rebuild 将是完美的
【解决方案2】:

我的理解是Visual Studio 2013 will finally solve this problem,但这对我没有多大好处,因为我仍在使用 Visual Studio 2012。经过大量努力,我终于遇到了solution

在包含您要运行的模板的项目中,在项目属性页面的“构建事件”选项卡上添加以下内容作为预构建步骤。

set textTransformPath="%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\TextTransform.exe"
if %textTransformPath%=="\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\TextTransform.exe" set textTransformPath="%CommonProgramFiles%\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\TextTransform.exe"
set ProjectDir=$(ProjectDir)
%textTransformPath% "%ProjectDir%StringGenerator.tt"

前两行处理在 32 位和 64 位系统上定位 TextTransform.exe 之间的区别。第三行是关键。我需要模板中项目位置的路径,因此我设置了一个本地环境变量,该变量等于构建的$(ProjectDir) 属性的值。在我的模板中,只需使用以下内容:

var projectDir = Environment.GetEnvironmentVariable("ProjectDir");

这解决了我的问题。

【讨论】:

    【解决方案3】:

    我创建了一个单独的解决方案,其中包含我需要的引用程序集。我让我的 buildscript 先构建参考解决方案,然后转换模板,然后构建包含生成代码的解决方案。

    【讨论】:

      【解决方案4】:

      如果您想使用宏在 T4 脚本中引用依赖程序集并在构建时成功进行文本模板化,那么您必须使用项目属性。

      在您的项目中:

        <Import Project="$(ProgramFiles)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\TextTemplating\Microsoft.TextTemplating.targets" />
        <PropertyGroup>
          <T4ProjectDir>$(ProjectDir)</T4ProjectDir>
        </PropertyGroup>
        <ItemGroup>
         <T4ParameterValues Include="T4ProjectDir">
          <Value>$(T4ProjectDir)</Value>
          <Visible>false</Visible>
         </T4ParameterValues>
        </ItemGroup>
      

      文本模板环境的路径可能不同。

      然后像在文本模板中使用任何其他宏一样使用 $(T4ProjectDir)。

      或者您也可以简单地引用现有属性:

        <ItemGroup>
         <T4ParameterValues Include="ProjectDir">
          <Value>$(ProjectDir)</Value>
          <Visible>false</Visible>
         </T4ParameterValues>
        </ItemGroup>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-27
        • 1970-01-01
        • 2012-01-23
        • 1970-01-01
        • 1970-01-01
        • 2014-06-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多