T4禁止错误消息“ErrorGeneratingOutput”

时间:2012-06-21 09:01:36

标签: c# .net templates t4

我正在使用一组T4脚本,它为EF应用程序中的实体生成部分类。

因为部分类需要驻留在同一个程序集中,所以该脚本与实体类位于同一个项目中。它还需要在执行时访问已编译的程序集。

发生错误时,脚本将失败并显示输出“ErrorGeneratingOutput”。这将导致整个项目无法编译,因为生成的文件是.cs文件,(在那个时间点)无效内容。

这就是一个恶意依赖循环,只有在我从生成的文件中手动删除错误消息然后触发构建时才会被破坏。

如果有办法抑制错误信息(或用空字符串替换它),我的生活会容易得多。

所以问题是:我可以更改t4脚本的错误处理吗?

2 个答案:

答案 0 :(得分:2)

我不知道是否可能,但是, 您可以将T4脚本放在一个单独的项目中,并使用MSBuild Task将生成的文件复制到EF实体项目中。

您的解决方案应包含

  1. 您的EF实体项目,我们称之为实体
  2. 一个实体生成器项目(您将把T4脚本放在这里),称之为 EntitiesGenerator ,例如
  3. 您还需要为自定义MSBuild任务创建一个项目,该项目会将生成的C#文件复制到“实体”项目

    为此,请创建一个类库项目 MyBuildProcess

    参考以下程序集:

    • Microsoft.Build.Framework(位于C:\ Windows \ Microsoft.NET \ Framework \ v4.0.30319)

    现在,让我们编写自定义任务 将类文件添加到项目CopyGeneratedEntities.cs中,例如

    using System;
    using Microsoft.Build.Framework;
    using System.IO;
    
    namespace MyBuildProcess
    {
        public class CopyGeneratedEntities : ITask
        {
            private IBuildEngine _buildEngine;
            public IBuildEngine BuildEngine
            {
                get { return _buildEngine; }
                set { _buildEngine = value; }
            }
    
            private ITaskHost _hostObject;
            public ITaskHost HostObject
            {
                get { return _hostObject; }
                set { _hostObject = value; }
            }
    
            public bool Execute()
            {
            // Copy generated Product entity to EF project
                if (File.Exists(@"C:\MySolution\EntitiesGenerator\ProductEntity.cs"))
                {
                    File.Copy(@"C:\MySolution\EntitiesGenerator\ProductEntity.cs",
                        @"C:\MySolution\Entities\ProductEntity.cs", true);
                }
    
                return true;
            }
        }
    }
    

    构建项目

    现在编辑与您的T4项目( EntitiesGenerator )相对应的 .csproj 文件,并通过在<Project ... >标记下添加以下内容来引用自定义任务:

    <UsingTask AssemblyFile="C:\MySolution\Libs\MyBuildProcess.dll" 
        TaskName="MyBuildProcess.CopyGeneratedEntities" />
    

    并像这样调用任务(在csproj文件的末尾,在</Project>之前):

    <Target Name="AfterBuild">`
        <CopyGeneratedEntities />
    </Target>
    

    现在,当您构建 EntitiesGenerator 项目时, T4呈现您的实体,一旦构建结束,您的自定义任务就会被调用,您的文件将被复制到您的“实体”项目中。

    您只需要在第一代之后手动将生成的C#文件引用到您的实体项目, 然后他们只是被覆盖了。

    有关MSBuild的更多信息 看到。

    MSBuild Team Blog - How To: Implementing Custom Tasks

    Microsoft.Build Namespaces

答案 1 :(得分:2)

在某些情况下,可以轻松解决此问题。

就我而言,问题是加载T4脚本所在项目的DLL。汇编指令放在脚本的顶部区域(第5行)。所以我将输出扩展名更改为txt。

<#@ template language="C#" hostspecific="True" debug="True" #>
<#@ output extension="txt" #>
<#@assembly name="invalidAssemblyName"#>

然后我使用EntityFrameworkFileManager将实际输出放到另一个文件中。

<#@ include file="EF.Utility.CS.ttinclude"#>
<#
var fileManager = EntityFrameworkTemplateFileManager.Create(this);
fileManager.StartHeader();
fileManager.StartNewFile("Output.cs");
#>
//content
<#
fileManager.Process();
#>

当发生错误,无法加载程序集时,ErrorGeneratingOutput消息将打印到默认的.txt文件,在该文件中不会产生编译问题。如果可以加载程序集,则输出将打印到Output.cs文件中。

这样可以在修复初始问题后构建项目,开发人员也不必关心ErrorGeneratingOutput问题。