我有一个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");
也无济于事。有什么想法吗?
答案 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