运行T4模板时确定解决方案配置(调试/发布)

时间:2011-04-07 23:28:06

标签: t4

我有一个T4模板,可以根据标志输出优化内容或标准内容。目前我正在根据我的需要手动更改旗帜。

我喜欢做的是根据Visual Studio中的解决方案配置设置标志。如果设置为在调试模式下构建,我将输出标准内容。如果设置为在发布模式下构建,我会改为优化内容。我发现了另一个看起来很有希望的T4问题:T4 Text Template - Is it possible to get compilation symbols from host?

但是,在我的情况下,我想做类似以下的事情:

<#@ template language="C#" hostspecific="True" 
    compilerOptions="/d:$(ConfigurationName)" #>

因为我可以在汇编指令中使用$(SolutionDir):

<#@ assembly name="$(SolutionDir)\myreference.dll" #>

我认为/ d:$(ConfigurationName)会让我到达我需要去的地方,然后我可以执行以下操作来设置我的标志:

<#
#if Debug 
 optimize = false;
#else 
 optimize = true;
#endif 
#>
唉,这似乎不起作用。我也尝试过使用:

Host.ResolveParameterValue("-", "-", "ConfigurationName");

也无济于事。有什么想法吗?

3 个答案:

答案 0 :(得分:25)

我很快就会问,但我在this MSDN article的底部找到了一个片段,它让我得到了我需要的位置。这里的答案是使用IServiceProvider接口来获取Visual Studio DTE。这是完成它的代码(事先为硬编码的“Debug”道歉):

var serviceProvider = Host as IServiceProvider;
var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
var configName = dte.Solution.SolutionBuild.ActiveConfiguration.Name ;
optimize = (configName != "Debug"); 

<强>更新

此代码将检查活动项目的当前配置是否已启用优化。它仍然具有硬编码的属性名称,但更改的可能性更小。此外,使用项目的优化标志对我的场景很有意义(试图决定是否应该在我自己的代码中启用优化):

var serviceProvider = Host as IServiceProvider;
var dte = serviceProvider.GetService(typeof(EnvDTE.DTE)) as DTE;
config = dte.Solution
            .FindProjectItem(Host.TemplateFile)
            .ContainingProject
            .ConfigurationManager
            .ActiveConfiguration;
foreach(Property prop in config.Properties){
    if (prop.Name == "Optimize"){
        optimize = (bool)prop.Value;
        break;
    }
}

答案 1 :(得分:11)

对于试图在设计时(文件保存)以及at build-time(F5 / F6)获得此项工作的人,需要两种方法。

Emil描述了设计时方法。对于构建时,首先必须在项目文件中指定T4参数:

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

然后你必须在.tt:

的顶部引用它
<#@ parameter type="System.String" name="BuildConfiguration" #>

然后寻找恰好提供的那些:

string configurationName = Host.ResolveParameterValue("-", "-", "BuildConfiguration");
if (string.IsNullOrWhiteSpace(configurationName))
{
    var serviceProvider = (IServiceProvider)Host;
    var dte = (DTE)serviceProvider.GetService(typeof(DTE));
    configurationName = dte.Solution.SolutionBuild.ActiveConfiguration.Name;
}

如果您希望模板在两种方案中都有效,则必须包含两者的逻辑。设计时方法在构建时不起作用(DTE主机不在于提供解决方案),并且构建时方法在设计时不起作用(MSBuild不在于提供参数)。 / p>

答案 2 :(得分:0)

如果尝试在VS2017 ASP.Net Core项目中执行此操作,则以下是对我有用的解决方案,其中包含我的帖子here中的要点。

MSDN blog by Jeremy Kuhne和此blog by Thomas Levesque以及其他MSDN doc之类的其他链接帮助其在VS2017中工作。

我不必在.csproj文件的开头添加任何内容,因为VS2017具有默认情况下已包含的文件。

  

在Visual Studio 2017中,``文本模板转换''组件为   作为Visual Studio扩展的一部分自动安装   开发工作量。您也可以从个人安装   Visual Studio Installer的“组件”选项卡,在“代码”工具下   类别。从个人安装Modeling SDK组件   组件标签。

我最终在文件末尾做了以下.csproj更改:

  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
    <!-- Run the Transform task at the start of every build -->
    <TransformOnBuild>true</TransformOnBuild>
    <!-- -->
    <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>
    <!-- Transform every template every time -->
    <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
  </PropertyGroup>

  <!-- add AFTER import for $(MSBuildToolsPath)\Microsoft.CSharp.targets -->
  <Import Project="$(VSToolsPath)\TextTemplating\Microsoft.TextTemplating.targets" />

    <ItemGroup>
    <T4ParameterValues Include="BuildConfiguration">
        <Value>$(Configuration)</Value>
        <Visible>False</Visible>
    </T4ParameterValues>
  </ItemGroup>

    <Target Name="CreateT4ItemListsForMSBuildCustomTool" BeforeTargets="CreateT4ItemLists" AfterTargets="SelectItemsForTransform">
    <ItemGroup>
        <T4Transform Include="@(CreateT4ItemListsInputs)" Condition="'%(CreateT4ItemListsInputs.Generator)' == 'MSBuild:TransformAll'" />
    </ItemGroup>
  </Target>

在T4模板中:

<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ assembly name="EnvDTE" #>
<#  
    //Build time
    string configName = Host.ResolveParameterValue("-", "-", "BuildConfiguration");
    if (string.IsNullOrWhiteSpace(configName))
    {
        try
        {
            //Design time.
            var serviceProvider = (IServiceProvider)Host;
            EnvDTE.DTE dte = (EnvDTE.DTE)serviceProvider.GetService(typeof(EnvDTE.DTE));
            configName = dte.Solution.SolutionBuild.ActiveConfiguration.Name;
        }
        catch(Exception ex)
        {
            configName = ex.Message;
        }
    }
#>
<#=configName#>

.tt文件上的以下属性设置:

Build Action: None
Copy to Output Directory: Do Not Copy
Custom Tool: MSBuild:TransformAll