使用自定义工具处理多个T4模板

时间:2014-10-30 14:06:52

标签: c# visual-studio code-generation t4 texttemplate

我有一个DSL模型和多个T4模板,可以生成与模型相对应的代码。我想要做的是在保存模型后执行所有模板。每个模板创建多个输出文件。理论上我知道如何为模型创建一个自定义工具来处理模板并返回生成的代码。但是我如何处理多个模板,因为IVsSingleFileGenerator接口返回一个生成的文件。

我想到的一种方法是创建一个" master" T4使用应处理的模板中的公共方法。但后来我在每个模板中写了数百个" Write()"因为"<#+"它不可能像模板的其余部分一样编写纯文本。或者我可以创建一个包含要生成的所有文件的代码的巨大模板。但我觉得这很丑陋而且很混乱。

或者有没有办法以某种方式实例化T4模板并让它处理和创建它自己的文件?我只知道如何实例化模板以便可以处理它,但我只获得了我自己处理的生成代码。

2 个答案:

答案 0 :(得分:0)

我不知道如何从类功能(<#+)生成文本,但它在MSDN中有描述:

Generate text from a class feature

<#+
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));
            }
}
#>

答案 1 :(得分:0)

因为我使用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);
    }
}