我正在使用一组 T4 脚本,这些脚本为 EF 应用程序中的实体生成分部类。
由于分部类需要驻留在同一个程序集中,因此脚本与实体类驻留在同一个项目中。它还需要在执行时访问已编译的程序集。
发生错误时,脚本将失败,输出"错误生成输出"。这将导致整个项目无法编译,因为生成的文件是一个.cs文件,包含(当时)无效内容。
所以这是一个恶性依赖循环,只有当我从生成的文件手动删除错误消息,然后触发构建时,才能打破它。
如果有一种方法可以抑制错误消息(或用空字符串替换它),我的生活会轻松得多。
所以问题是:我可以更改 t4 脚本的错误处理吗?
在某些情况下,这个问题可以很容易地解决。
就我而言,问题在于加载 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文件中,在该文件中,它不会给编译带来问题。如果可以加载程序集,则输出将打印到"输出.cs"文件。
这样,可以在修复初始问题后构建项目,开发人员也不必关心ErrorGeneratingOutput问题。
这是否可能,但是,可以将 T4 脚本放在单独的项目中,并使用 MSBuild 任务将生成的文件复制到 EF 实体项目。
您的解决方案应包含
- EF 实体项目,我们将其称为实体 一个实体生成器
- 项目(您将把 T4 脚本放在这里),例如,将其称为实体生成器
还需要为自定义 MSBuild 任务创建一个项目,该项目会将生成的 C# 文件复制到"实体"项目
为此,请创建一个类库项目,MyBuildProcess
引用以下程序集:
- Microsoft.Build.Framework(位于 C:\Windows\Microsoft.NET\Framework\v4.0.30319)
现在,让我们编写自定义任务例如,将类文件添加到项目中,例如 CopyGenerated Entities.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:MySolutionEntitiesGeneratorProductEntity.cs"))
{
File.Copy(@"C:MySolutionEntitiesGeneratorProductEntity.cs",
@"C:MySolutionEntitiesProductEntity.cs", true);
}
return true;
}
}
}
构建您的项目
现在编辑与 T4 项目(实体生成器)对应的 .csproj 文件,并通过在 <Project ... >
标记下添加以下内容来引用自定义任务:
<UsingTask AssemblyFile="C:MySolutionLibsMyBuildProcess.dll"
TaskName="MyBuildProcess.CopyGeneratedEntities" />
并像这样调用任务(在csproj文件的末尾,在</Project>
之前):
<Target Name="AfterBuild">`
<CopyGeneratedEntities />
</Target>
现在,当您生成实体生成器项目时,T4 呈现实体,生成结束后,将调用自定义任务,并将文件复制到"实体"项目。
只需在第一代生成后手动将生成的 C# 文件引用到实体项目,然后它们只是被覆盖。
有关 MSBuild 的详细信息看。
MSBuild 团队博客 - 如何:实现自定义任务
Microsoft.构建命名空间