0

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

我考虑的一种方法是创建一个“主”T4,它使用来自要处理的模板的公共方法。但是我必须在每个模板中编写丑陋的方法,其中包含数百个“Write()”调用,因为在“<#+”内部不可能像在模板的其余部分中那样编写纯文本。或者我可以创建一个巨大的模板,其中包含要生成的所有文件的代码。但我认为这很丑陋而且非常令人困惑。

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

4

2 回答 2

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);
    }
}
于 2014-11-10T19:10:29.743 回答
0

我不知道如何从类特征 (<#+) 生成文本,但它在 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));
            }
}
#>
于 2014-10-30T14:26:52.573 回答