Обрабатывать несколько шаблонов T4 с помощью специального инструмента

У меня есть модель DSL и несколько шаблонов T4, которые генерируют код, соответствующий модели. Что я хочу сделать, так это то, что ВСЕ шаблоны выполняются при сохранении модели. Каждый шаблон создает несколько выходных файлов. Я теоретически знаю, как создать пользовательский инструмент для модели, который будет обрабатывать шаблон и возвращать сгенерированный код. Но как я могу обрабатывать несколько шаблонов, так как интерфейс IVsSingleFileGenerator возвращает один сгенерированный файл.

Один из способов, о котором я думаю, - это создать "главный" T4, который использует открытые методы из шаблонов, которые должны быть обработаны. Но затем я должен написать уродливые методы в каждом шаблоне с сотнями вызовов "Write()", потому что внутри "<# +" невозможно написать простой текст, как в остальной части шаблона. Или я мог бы создать один огромный шаблон, который содержит код для ВСЕХ файлов, которые будут сгенерированы. Но это уродливо и очень запутанно, я думаю.

Или есть способ как-то создать экземпляр шаблона T4 и позволить ему обрабатывать и создавать файлы самостоятельно? Я знаю только, как создать экземпляр шаблона, чтобы он мог быть обработан, но я получаю только сгенерированный код, который я должен обрабатывать самостоятельно.

2 ответа

Решение

Поскольку я использую MultipleOutputHelper, у меня есть контроль над файлами, которые создаются. Это делает обработку нескольких шаблонов в генераторе кода очень простой:

public class MyCodeGenerator : TemplatedCodeGenerator
{
    protected override byte[] GenerateCode(string inputFileName, string inputFileContent)
    {
        ProcessTemplate(inputFileName, CodeGenerationResource.TemplateX);
        ProcessTemplate(inputFileName, CodeGenerationResource.TemplateY);

        // since we're using the MultipleOutputHelper class in the t4 templates, which generates the required files on its own, we don't have to return any bytes
        return new byte[0];
    }

    private void ProcessTemplate(string inputFileName, string templateContent)
    {
        var fi = new FileInfo(inputFileName);
        templateContent = templateContent.Replace("Sample.mmd", fi.Name);
        base.GenerateCode(inputFileName, templateContent);
    }
}

Я не знал, как генерировать текст из функции класса (<# +), но это описано в MSDN:

Генерация текста из объекта класса

<#+
private void CreateAccessor(ModelClass classType, ModelClass associatedClass, string      fromRoleName, string toRoleName)
{
            if(!string.IsNullOrEmpty(toRoleName) && !string.IsNullOrEmpty(fromRoleName))
            {
               string validClassName = MakeValidName(associatedClass.Name);
               string validFromName = MakeValidName(fromRoleName);
               string validToName = MakeValidName(toRoleName);
#>

private <#= validClassName#> <#= validFromName#>Value;
public <#= validClassName#> <#= validFromName#>
{
    get{ return <#= validFromName #>Value; }
    set
    {
       if (<#= validFromName#> != value)
       {
if (<#= validFromName#> != null) 
<#= validFromName#>.<#=validToName#> = null;
<#= validFromName#>Value = value;
if (value != null) 
{
        <#= validFromName#>Value.<#=validToName#>=this;
}
   }
        }
    }
<#+
            }
            else
            {
                Warning(String.Format("Ignoring BidirectionalAssociation from {0} to {1} because its SourceRoleName or TargetRoleName is not defined", classType.Name, associatedClass.Name));
            }
}
#>
Другие вопросы по тегам