3

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

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

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

所以这是一个恶性依赖循环,只有我手动从生成的文件中删除错误信息,然后触发构建才能打破。

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

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

4

2 回答 2

3

在某些情况下,这个问题很容易解决。

就我而言,问题在于加载 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问题。

于 2012-07-02T14:54:50.180 回答
2

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

您的解决方案应包含

  1. 您的 EF 实体项目,我们称之为实体
  2. 一个实体生成器项目(你将把你的 T4 脚本放在这里),例如称之为EntitiesGenerator

您还需要为自定义 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 团队博客 - 如何:实施自定义任务

Microsoft.Build 命名空间

于 2012-06-29T14:45:42.013 回答