【问题标题】:T4 indent code included from another file另一个文件中包含的 T4 缩进代码
【发布时间】:2021-08-06 06:16:38
【问题描述】:

假设您有一个模板,您希望在其中包含来自另一个文件的代码。假设模板名为Template.tt,内容如下:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="App" #>

namespace <#= Namespace #>
{
    public partial class <#= ClassName #>
    {
<#@ include file="Snippet.txt" #>
    }
}

Snippet.txt 包含类主体的代码,尾随换行符:

public void Function() 
{
}

但是,如果您尝试运行该模板,您会得到如下所示的代码:

namespace MyNamespace
{
    public partial class MyClass
    {
public void Function() 
{
}
    }
}

缩进的一种方法是将包含文件中的每一行缩进所需的数量。然而,这不是一个令人满意的解决方案。有什么想法吗?

【问题讨论】:

    标签: c# formatting t4


    【解决方案1】:

    我们的想法是在你的模板中使用函数PushIndent()PopIndent(),如下所示:

    namespace <#= Namespace #>
    {
        public partial class <#= ClassName #>
        { <# PushIndent("        "); #>
    
    <#@ include file="Snippet.txt" #>
    <# PopIndent(); #>
    
        }
    }
    

    除非这不起作用,因为生成的打印机代码使用函数Write() 来打印输出,但是,Write() 忽略缩进...

    但是!您实际上可以控制您的模板最终调用什么函数实现来打印输出。当 T4 为您的代码生成打印机类时,它会自动创建一个基类,其中包含 Write()WriteLine()TransformText() 等函数。然后,生成的模板设置为从该类继承,将 TransformText() 覆盖为打印他们自己的文本。

    这个想法是提供你自己的基类,它符合该基类的鸭接口,以使Write()使用缩进。 T4 允许您这样做!参见例如this blogpost for starters

    要使用缩进,请注意它们仅用于新行。然后,将Write() 更改为以下内容:

    public void Write(string textToAppend) 
    {
         GenerationEnvironment.Append(textToAppend.Replace("\r\n", "\r\n" + currentIndent));
    }
    

    并从模板中的基类继承(例如,基类的名称是CodePrinterBase):

    <#@ template debug="false" hostspecific="true" language="C#" inherits="CodePrinterBase" #>
    <#@ assembly name="App" #>
    
    namespace <#= Namespace #>
    {
        public partial class <#= ClassName #>
        { <# PushIndent("        "); #>
    
    <#@ include file="Snippet.txt" #>
    <# PopIndent(); #>
    
        }
    }
    

    结果:

    namespace MyNamespace
    {
        public partial class MyClass
        {
            public void Function() 
            {
            }
    
        }
    }
    

    如果您还想删除 sn-p 之后的新行,请删除该 sn-p 中的尾随新行。

    需要明确的是,PushIndent() 在括号之后,因为需要在代码运行之后插入新行。如果你把它放在括号下面并在它后面留下一个空行,如下所示,你会在输出中得到一个额外的空行:

    { 
    <# PushIndent("        "); #>
    
    <#@ include file="Snippet.txt" #>
    

    跑步会给你带来:

    namespace MyNamespace
    {
        public partial class MyClass
        {
    
            public void Function() 
            {
            }
    
        }
    }
    

    这对我来说完美无缺!

    【讨论】:

      猜你喜欢
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多