我想创建一个工具作为T4模板的基类,以便在Visual Studio .NET中的设计时生成代码。我希望我的TextTransformation派生基类能够最终说明输出到生成文件的内容。问题是使用.NET反射器我找不到一个方法,我可以覆盖(或声明为新)或任何事件,以便在它被T4框架使用之前更改GenerationEnvironment属性的内容。
以下是基类的示例:
public class MyTool
: TextTransformation
{
public override void Initialize()
{
// Initialize My Tool
base.Initialize();
}
// Override the text that is generated from the T4 template and modify it
// (strip out some well known .NET attributes) here.
}
它将继承自T4模板,如下所示:
<#@ template debug="false" hostspecific="true" language="C#" inherits="MyTool" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="MyTool.dll" #>
<#@ assembly name="Microsoft.VisualStudio.TextTemplating.10.0" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="MyTool" #>
<#@ output extension=".cs" #>
[Ender]
public interface INinjaEnder
{
INinja Build();
}
[Required]
public interface INinjaNamed<TRemainder>
{
TRemainder Named(string name);
}
public interface INinjaCostume<TRemainder>
{
TRemainder WithCostume(Costume costume);
}
我可以在MyTool中的Initialize()方法或Dispose()方法(覆盖时)中查找断点,但似乎没有任何东西可用于修改输出。我正在考虑的一些选择:
Dispose()
方法创建一个单独的文件以输出更改的内容,并完全忽略T4模板的输出。遗憾的是,在Dispose()
方法中生成具有相同名称的文件不起作用,因为它会被原始文本覆盖。WriteLine()
和/或Write()
方法(使用new)并使用它们去除最终文件中我不想要的文本。这可能需要在GenerationEnvironment的输出上进行RegEx匹配,这样我就可以看到代码是否在那里并且在剥离之前完全生成。我还想过将StringBuilder子类化为覆盖ToString()方法(GenerationEnvironment返回一个StringBuilder),但StringBuilder类是密封的。
我应该提一下,我的目标是Visual Studio 2010,2012和2013的所有版本(包括快速版)。我注意到2010年到2012年T4有一些很大的差异,所以我需要拿出来适用于两种环境的解决方案。
某些情境
我沿着这条道路前进的理由是:
但是,如果有比T4基类更好的选择,我会接受架构建议。