共用方式為


在建置程序中叫用文字轉換

如何在 Visual Studio 解決方案的建置程序中叫用文字轉換。 有的建置工作會針對文字轉換進行特製化。 T4 建置工作會執行設計階段的文字範本,也會編譯執行階段 (前置處理過後) 的文字範本。

根據不同的建置引擎,建置工作可執行的動作會有些差異。 在 Visual Studio 中建置解決方案時,如果已設定 hostspecific="true" 屬性,文字範本即可存取 Visual Studio API (EnvDTE)。 但在您從命令列建置方案或透過 Visual Studio 啟始伺服器組建時,這並不正確。 在這些情況下,會由 MSBuild 執行組建,並會使用不同的 T4 主機。 這表示使用 MSBuild 建置文字範本時,您無法以相同方式來存取如專案檔名之類的項目。 不過,您可以使用組建參數傳遞環境資訊至文字範本和指示詞處理器中

設定您的電腦

若要在開發電腦上啟用建置工作,請安裝適用於 Visual Studio 的模型化 SDK。

注意

文字範本轉換元件會作為 Visual Studio 延伸模組開發工作負載的一部分自動安裝。 您也可以從 Visual Studio 安裝程式的 [個別元件] 索引標籤加以安裝,其位於 [SDK、程式庫和架構] 底下。 從 [個別元件] 索引標籤安裝 [模型化 SDK] 元件。

如果執行組建伺服器的電腦未安裝 Visual Studio,請從開發電腦將下列檔案複製到組建電腦:

  • %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VisualStudio\v16.0\TextTemplating

    • Microsoft.VisualStudio.TextTemplating.Sdk.Host.15.0.dll
    • Microsoft.TextTemplating.Build.Tasks.dll
    • Microsoft.TextTemplating.targets
  • %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VSSDK\VisualStudioIntegration\Common\Assemblies\v4.0

    • Microsoft.VisualStudio.TextTemplating.15.0.dll
    • Microsoft.VisualStudio.TextTemplating.Interfaces.15.0.dll
    • Microsoft.VisualStudio.TextTemplating.VSHost.15.0.dll
  • %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\Common7\IDE\PublicAssemblies

    • Microsoft.VisualStudio.TextTemplating.Modeling.15.0.dll

提示

如果您在組建伺服器上執行 TextTemplating 建置目標時,取得 Microsoft.CodeAnalysis 方法的 MissingMethodException,請確定 Roslyn 組件位於與組建可執行檔相同目錄且名為 Roslyn 的目錄中(例如 msbuild.exe)。

編輯專案檔

編輯專案檔,以設定 MSBuild 中的部分功能,例如匯入文字轉換目標。

在 [方案總管] 中,從您專案的右鍵功能表中選擇 [卸載]。 如此可讓您在 XML 編輯器中編輯 .csproj 或 .vbproj 檔案。 當您完成編輯時,請選擇 [重新載入]

匯入文字轉換目標

在 .vbproj 或 .csproj 檔案中,尋找最後一個 Import Project 行。

在該行 (存在的話) 之後,插入文字範本化匯入:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v17.0\TextTemplating\Microsoft.TextTemplating.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v16.0\TextTemplating\Microsoft.TextTemplating.targets" />

在組建中轉換範本

其中具有可輸入至專案檔以控制轉換工作的一些屬性:

  • 在每個組建的開始處執行轉換工作:

    <PropertyGroup>
        <TransformOnBuild>true</TransformOnBuild>
    </PropertyGroup>
    
  • 覆寫唯讀的檔案,因為它們未被簽出:

    <PropertyGroup>
        <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>
    </PropertyGroup>
    
  • 每次轉換每一個範本:

    <PropertyGroup>
        <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
    </PropertyGroup>
    

    根據預設,T4 MSBuild 工作會重新產生輸出檔案,前提是輸出檔案早於:

    • 其範本檔
    • 任何包含的檔案
    • 先前由範本或其所用指示詞處理器讀取的任何檔案

    相較於 Visual Studio 中的 [轉換所有範本] 命令所用的相依性測試只會比較範本和輸出檔案的日期,這是更為強大的相依性測試。

若在專案中僅執行文字轉換,請叫用 TransformAll 工作:

msbuild myProject.csproj /t:TransformAll

轉換特定文字範本:

msbuild myProject.csproj /t:Transform /p:TransformFile="Template1.tt"

您可以在 TransformFile 中使用萬用字元:

msbuild dsl.csproj /t:Transform /p:TransformFile="GeneratedCode\**\*.tt"

原始檔控制

與原始檔控制系統的特定內建整合並未提供。 不過,您可以新增自己的延伸模組,例如簽出並簽入所產生的檔案。 根據預設,文字轉換工作會避免覆寫標示為唯讀的檔案。 遇到這類檔案時,Visual Studio 錯誤清單中會記錄錯誤,且工作會失敗。

若要指定必須覆寫唯讀檔案,請插入以下屬性:

<OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>

除非您自訂後置處理步驟,否則覆寫檔案時就會將警告記錄於錯誤清單中。

自訂建置程序

文字轉換會在建置程序的其他工作之前運作。 藉由設定 $(BeforeTransform)$(AfterTransform) 屬性,您可以定義轉換之前和之後叫用的工作:

<PropertyGroup>
    <BeforeTransform>CustomPreTransform</BeforeTransform>
    <AfterTransform>CustomPostTransform</AfterTransform>
</PropertyGroup>
<Target Name="CustomPreTransform">
    <Message Text="In CustomPreTransform..." Importance="High" />
</Target>
<Target Name="CustomPostTransform">
    <Message Text="In CustomPostTransform..." Importance="High" />
</Target>

AfterTransform 中,您可以參考檔案清單:

  • GeneratedFiles:流程所寫入之檔案的清單。 對於已覆寫現有唯讀檔的檔案而言,%(GeneratedFiles.ReadOnlyFileOverwritten) 會是 true。 您可以從原始檔控制中簽出這些檔案。

  • NonGeneratedFiles:不會遭到覆寫之唯讀檔案的清單。

例如,您可以定義工作以檢查 GeneratedFiles。

OutputFilePath 和 OutputFileName

這些屬性只能由 MSBuild 使用。 它們並不會影響在 Visual Studio 中產生的程式碼。 它們會將產生的輸出檔重新導向至不同資料夾或檔案。 目標資料夾必須已經存在。

<ItemGroup>
  <None Include="MyTemplate.tt">
    <Generator>TextTemplatingFileGenerator</Generator>
    <OutputFilePath>MyFolder</OutputFilePath>
    <LastGenOutput>MyTemplate.cs</LastGenOutput>
  </None>
</ItemGroup>

有一個可重新導向至的資料夾為 $(IntermediateOutputPath)

如果您指定輸出檔名,則會優先於範本中輸出指示詞指定的副檔名。

<ItemGroup>
  <None Include="MyTemplate.tt">
    <Generator>TextTemplatingFileGenerator</Generator>
    <OutputFileName>MyOutputFileName.cs</OutputFileName>
    <LastGenOutput>MyTemplate.cs</LastGenOutput>
  </None>
</ItemGroup>

在 Visual Studio 中,同時使用 [全部轉換] 或執行單一檔案產生器時,不建議指定 OutputFileName 和 OutputFilePath。 根據觸發轉換的方法,最後將會產生不同的檔案路徑。 這可能有些困擾。

新增參考和包含路徑

主機具有搜尋範本中所參考組件的預設路徑集合。 加入至這個集合:

<ItemGroup>
    <T4ReferencePath Include="$(VsIdePath)PublicAssemblies\" />
    <!-- Add more T4ReferencePath items here -->
</ItemGroup>

若要設定搜尋包含檔案的資料夾,請提供以分號分隔的清單。 通常會加入至現有的資料夾清單。

<PropertyGroup>
    <IncludeFolders>
$(IncludeFolders);$(MSBuildProjectDirectory)\Include;AnotherFolder;And\Another</IncludeFolders>
</PropertyGroup>

將組建內容資料傳入範本中

您可以在專案檔中設定參數值。 例如,您可以傳遞組建屬性和環境變數

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

在文字範本內,在範本指示詞中設定 hostspecific。 使用參數指示詞取得值:

<#@template language="c#" hostspecific="true"#>
<#@ parameter type="System.String" name="ProjectFolder" #>
The project folder is: <#= ProjectFolder #>

在指示詞處理器中,您可以呼叫 ITextTemplatingEngineHost.ResolveParameterValue

string value = Host.ResolveParameterValue("-", "-", "parameterName");

注意

只有在您使用 MSBuild 時,ResolveParameterValue 才會從 T4ParameterValues 取得資料。 使用 Visual Studio 轉換範本時,參數會有預設值。

在 assembly 和 include 指示詞中使用專案屬性

Visual Studio 巨集 (如 $(SolutionDir)) 在 MSBuild 中無法運作。 您可以改用專案屬性。

編輯您的 .csproj.vbproj 檔案以定義專案屬性。 這個範例會定義名為 myLibFolder 的屬性:

<!-- Define a project property, myLibFolder: -->
<PropertyGroup>
    <myLibFolder>$(MSBuildProjectDirectory)\..\libs</myLibFolder>
</PropertyGroup>

<!-- Tell the MSBuild T4 task to make the property available: -->
<ItemGroup>
    <T4ParameterValues Include="myLibFolder">
      <Value>$(myLibFolder)</Value>
    </T4ParameterValues>
  </ItemGroup>

您現在可以在 assembly 和 include 指示詞中使用專案屬性:

<#@ assembly name="$(myLibFolder)\MyLib.dll" #>
<#@ include file="$(myLibFolder)\MyIncludeFile.t4" #>

這些指示詞會從 MSBuild 和 Visual Studio 裝載中的 T4parameterValues 取得值。

問與答

為何需要在組建伺服器中轉換範本? 在簽入程式碼之前,我已經在 Visual Studio 中轉換範本。

如果更新包含的檔案或範本讀取的其他檔案,Visual Studio 並不會自動轉換檔案。 轉換範本為組建的一部分,以確保一切皆維持在最新狀態。

其他轉換文字範本的選項為何?

  • T4 MSbuild 範本中有良好的指引 (位於 %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VisualStudio\v17.0\TextTemplating\Microsoft.TextTemplating.targets)
  • T4 MSbuild 範本中有良好的指引 (位於 %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Enterprise\msbuild\Microsoft\VisualStudio\v16.0\TextTemplating\Microsoft.TextTemplating.targets)