来自另一个文件的 T4 缩进代码
T4 indent code included from another file
假设您有一个模板,您希望在其中包含来自另一个文件的代码。假设模板名为 Template.tt
并具有以下内容:
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="App" #>
namespace <#= Namespace #>
{
public partial class <#= ClassName #>
{
<#@ include file="Snippet.txt" #>
}
}
Snippet.txt
包含 class 正文的代码,尾随换行符:
public void Function()
{
}
但是,如果您尝试 运行 模板,您会得到如下所示的代码:
namespace MyNamespace
{
public partial class MyClass
{
public void Function()
{
}
}
}
缩进的一种方法是将包含文件中的每一行缩进所需的数量。然而,这不是一个令人满意的解决方案。有什么想法吗?
想法是在模板中使用函数 PushIndent()
和 PopIndent()
,如下所示:
namespace <#= Namespace #>
{
public partial class <#= ClassName #>
{ <# PushIndent(" "); #>
<#@ include file="Snippet.txt" #>
<# PopIndent(); #>
}
}
除非这行不通,因为生成的打印机代码使用函数 Write()
来打印输出,但是,Write()
忽略缩进...
但是!您实际上可以控制您的模板最终调用什么函数实现来打印输出。当 T4 为您的代码生成打印机 class 时,它会自动创建一个具有 Write()
、WriteLine()
、TransformText()
等函数的基 class。然后,生成的模板设置为继承 class,覆盖 TransformText()
以打印自己的文本。
想法是提供您自己的基础 class,它符合该基础 class 的 duck 接口,以便 Write()
使用缩进。 T4 让你做到这一点!例如参见 [=28=].
要使用缩进,请注意只有换行时才需要缩进。然后,将 Write()
更改为以下内容:
public void Write(string textToAppend)
{
GenerationEnvironment.Append(textToAppend.Replace("\r\n", "\r\n" + currentIndent));
}
并从模板中的基础 class 继承(例如,基础 classes 的名称是 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()
{
}
}
}
如果您还想删除代码段后的新行,请删除该代码段中尾随的新行。
需要说明的是,PushIndent()
是在括号之后,因为需要在 代码 运行 之后插入新行。如果你把它放在括号下面并在它后面留一个空行,如下所示,你会在输出中得到一个额外的空行:
{
<# PushIndent(" "); #>
<#@ include file="Snippet.txt" #>
运行 那会给你:
namespace MyNamespace
{
public partial class MyClass
{
public void Function()
{
}
}
}
这对我来说完美无缺!
假设您有一个模板,您希望在其中包含来自另一个文件的代码。假设模板名为 Template.tt
并具有以下内容:
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="App" #>
namespace <#= Namespace #>
{
public partial class <#= ClassName #>
{
<#@ include file="Snippet.txt" #>
}
}
Snippet.txt
包含 class 正文的代码,尾随换行符:
public void Function()
{
}
但是,如果您尝试 运行 模板,您会得到如下所示的代码:
namespace MyNamespace
{
public partial class MyClass
{
public void Function()
{
}
}
}
缩进的一种方法是将包含文件中的每一行缩进所需的数量。然而,这不是一个令人满意的解决方案。有什么想法吗?
想法是在模板中使用函数 PushIndent()
和 PopIndent()
,如下所示:
namespace <#= Namespace #>
{
public partial class <#= ClassName #>
{ <# PushIndent(" "); #>
<#@ include file="Snippet.txt" #>
<# PopIndent(); #>
}
}
除非这行不通,因为生成的打印机代码使用函数 Write()
来打印输出,但是,Write()
忽略缩进...
但是!您实际上可以控制您的模板最终调用什么函数实现来打印输出。当 T4 为您的代码生成打印机 class 时,它会自动创建一个具有 Write()
、WriteLine()
、TransformText()
等函数的基 class。然后,生成的模板设置为继承 class,覆盖 TransformText()
以打印自己的文本。
想法是提供您自己的基础 class,它符合该基础 class 的 duck 接口,以便 Write()
使用缩进。 T4 让你做到这一点!例如参见 [=28=].
要使用缩进,请注意只有换行时才需要缩进。然后,将 Write()
更改为以下内容:
public void Write(string textToAppend)
{
GenerationEnvironment.Append(textToAppend.Replace("\r\n", "\r\n" + currentIndent));
}
并从模板中的基础 class 继承(例如,基础 classes 的名称是 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()
{
}
}
}
如果您还想删除代码段后的新行,请删除该代码段中尾随的新行。
需要说明的是,PushIndent()
是在括号之后,因为需要在 代码 运行 之后插入新行。如果你把它放在括号下面并在它后面留一个空行,如下所示,你会在输出中得到一个额外的空行:
{
<# PushIndent(" "); #>
<#@ include file="Snippet.txt" #>
运行 那会给你:
namespace MyNamespace
{
public partial class MyClass
{
public void Function()
{
}
}
}
这对我来说完美无缺!