Определите конфигурацию решения (отладка / выпуск) при запуске шаблона T4 - PullRequest
24 голосов
/ 08 апреля 2011

У меня есть шаблон T4, который может выводить либо оптимизированный контент, либо стандартный контент на основе флага. В настоящее время я вручную изменяю флаг в зависимости от своих потребностей.

Я бы хотел установить флаг на основе конфигурации решения в Visual Studio. Если установить для сборки в режиме отладки, я бы вывел стандартный контент. Если установить для сборки в режиме выпуска, я бы оптимизировал контент вместо этого. Я нашел другой вопрос T4, который выглядит многообещающим: Текстовый шаблон T4 - возможно ли получить символы компиляции с хоста?

Однако в моем случае я хотел бы сделать что-то вроде следующего:

<#@ 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 ]

25 голосов
/ 08 апреля 2011

Не успею я спросить, но в нижней части этой статьи MSDN я найду фрагмент, который доставит меня туда, где я должен быть.Ответ здесь заключается в использовании интерфейса IServiceProvider для получения Visual Studio DTE .Вот код, который делает это (заранее извиняюсь за жестко запрограммированный «Отладка»):

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;
    }
}
11 голосов
/ 26 ноября 2014

Для людей, пытающихся получить эту работу во время разработки (сохранение файла), а также во время сборки (F5 / F6), необходимы два метода.

Эмиль описывает метод времени разработки. Для времени сборки сначала необходимо указать параметр 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 не существует для предоставления параметра).

0 голосов
/ 24 октября 2018

Если попытаться сделать это в проекте VS2017 ASP.Net Core, то мне поможет следующее решение с основными моментами из моего поста здесь .

Этот блог MSDN Джереми Кюне и этот блог Томаса Левеска и несколько других ссылок, таких как Документ MSDN , помогли ему работать в VS2017.

Мне не нужно было ничего добавлять в начало файла .csproj, поскольку в VS2017 файлы уже включены по умолчанию.

В Visual Studio 2017 компонент преобразования текстовых шаблонов автоматически устанавливается как часть расширения Visual Studio рабочая нагрузка Вы также можете установить его из Индивидуального Вкладка «Компоненты» установщика Visual Studio под инструментами «Код» категория. Установите компонент 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
...