Обрабатывать несколько шаблонов 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));
}
}
#>