如何禁用在T4代码生成输出文件中写入#line指令

23

在我的T4代码生成中遇到了一个小问题。

我将T4模板分解成不同的文件并放置在各个目录中,这样我的代码生成的部分可以在多个项目中重复使用,例如模型生成、存储库生成和服务生成都包括一个核心的EntityGeneration.tt文件。

不幸的是,当TextTemplating解析我的嵌套include时,在生成的.cs文件中会构建出一个很长的#line预处理器指令,结合所有相对路径到最低级别的包含文件。

不幸的是,由于这个路径是由相对路径构建的,它变得过长,实际上超过了最大路径长度(Windows 7)。

如果您有兴趣,以下是生成代码中有问题的行:

#line 3 "C:\VS2010\AlbatrossTravelGroup\ASC\AlbatrossTravelGroup.ASC.BusinessRules\Services\Contracts\..\..\..\..\AlbatrossTravelGroup.BusinessRules\Services\Contracts\..\..\..\AlbatrossTravelGroup.Models\Repositories\Contracts\..\..\../AlbatrossTravelGroup.Common/CodeGeneration.tt"
我的问题是,我该如何禁用这些指令被写入生成的代码文件中?如果无法做到这一点,我该如何避免在不改变文件结构的情况下解决此问题?

2
目前,作为一个临时解决方案,我创建了一个名为“CodeGeneration”的文件夹,并在该文件夹中创建了符号链接,以包含每个T4文件。然后,每个包含的T4文件不再通过相对路径包含其他T4文件,而是仅使用文件名。然后,在我希望使用这些T4模板的最终位置,我使用相对路径到“CodeGeneration”目录。这将导致路径长度大大缩短,因为它使用了更少的相对路径。如果有人想要完整的解释,我可以在请求时发布答案 :) - Lukazoid
1
我的临时解决方案出了问题,不知道为什么,因为Visual Studio突然无法解析文件。最终我不得不使用注册表来指定额外的tt包含目录,这不是理想的选择,但似乎是唯一可行的方法。 - Lukazoid
你可以尝试使用这里提供的VS宏解决方案:https://dev59.com/b0_Ta4cB1Zd3GeqPEdg-#7505247。 - BitMask777
2个回答

21

这在VS 2019中也适用。它还禁用了“#line hidden”和“#line default”指令。 - kwitee

0

我不确定这会解决你的问题。我在 T4 方面没有太多经验。话虽如此,我正在使用它来构建项目中的许多文件,并且我没有遇到你遇到的问题。

在我的情况下,我有一堆单独的 .tt 文件,它们渲染项目中的单独文件。

我使用的方法如下:我有一个 SaveOutput 方法(我相信是从 stackoverflow 上借鉴来的):

void SaveOutput(string outputFileName)
{
    if (!string.IsNullOrEmpty(outputFileName))
    {
        string templateDirectory = Path.GetDirectoryName(Host.TemplateFile);
        string outputFilePath = Path.Combine(templateDirectory, outputFileName);
        string output = this.GenerationEnvironment.ToString();
        File.WriteAllText(outputFilePath, output); 
    }

    this.GenerationEnvironment.Remove(0, this.GenerationEnvironment.Length);
}

在我的主 .tt 文件中,我有 <#@ includes... #> 用于我的各个单独文件的各种 .tt 文件。例如:<#@ include file="DataObjectInterface.tt" #>。
<#+
    public string GenerateInterfaceDataObject(sqlTable table)
    {
        string ifaceName = "I" + table.ObjectName;
        if (table.GenerateInterfaceObjectAsBase)
        {
            ifaceName += "Base";
        }
#>
using System;

namespace <#= InterfaceNamespace #>
{
    public interface <#= ifaceName #>
    {
<#+
        foreach(sqlColumn col in table.Columns)
        {
#>
        <#= GetColumnCSharpDataType(col) #> <#= col.FieldName #> { get; }
<#+
        }
#>
    }
}
<#+
        return RootPath + @"\AutoGenerated\" + ifaceName + ".cs";
    }
#>

然后,在我的主 .tt 类中,我只需像这样调用:

string filePath = GenerateInterfaceDataObject(table);
SaveOutput(filePath);

不确定这种将模板分解的方法是否适合您的需求,但它适合我的需求,并且我还没有遇到任何问题。

我应该澄清一下,我的主要.tt文件实际上并不从自身生成任何内容。它本身不是一个模板。它只是加载每个模板并从其他模板生成文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接