0

DSL モデルと、モデルに対応するコードを生成する複数の T4 テンプレートがあります。私がやりたいことは、モデルの保存時にすべてのテンプレートが実行されることです。各テンプレートは、複数の出力ファイルを作成します。テンプレートを処理して生成されたコードを返すモデル用のカスタム ツールを作成する方法を理論的に知っています。しかし、IVsSingleFileGenerator インターフェイスは生成された単一のファイルを返すため、複数のテンプレートを処理するにはどうすればよいでしょうか。

私が考える 1 つの方法は、処理されるテンプレートのパブリック メソッドを使用する「マスター」T4 を作成することです。しかし、「<#+」の内部では、テンプレートの残りの部分のようにプレーンテキストを書くことができないため、各テンプレートに何百もの「Write()」呼び出しを含む醜いメソッドを記述しなければなりません。または、生成されるすべてのファイルのコードを含む 1 つの巨大なテンプレートを作成することもできます。しかし、それは醜く、非常に紛らわしいと思います。

または、何らかの方法で 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 に答える