防止T4模板删除现有文件

时间:2011-05-09 17:29:32

标签: entity-framework t4

我想为我的edmx-model中的每个实体创建一个名为{0} Validator.cs的独立类文件(现在不关心它的内容)。

这似乎有效,但我无法解决这个问题,以防止我的T4模板首先删除我的所有文件。我怎样才能摆脱这种行为?

我发现如果我调用fileManager.Process(true),我的validator.tt文件下的所有文件都将被重新创建(我不希望这样)。

有什么想法吗? 谢谢!

<#@ template language="C#" debug="false" hostspecific="true"#>
//<#@ include file="EF.Utility.CS.ttinclude"#>
<#@output extension=".cs"#>

<#
CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
CodeRegion region = new CodeRegion(this, 1);

string inputFile =@"ServicesEntities.edmx";
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
string namespaceName = code.VsNamespaceSuggestion();

EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);

// for test purposes only...
fileManager.Process(true);

// for each entity, create a xxxValidator.cs file

foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
{
     string fileName = entity.Name + "Validator.cs";
     string filePath = this.Host.TemplateFile.Substring(0,this.Host.TemplateFile.LastIndexOf(@"\")); 
     filePath = filePath + @"\" + fileName;

     if(!File.Exists(filePath)) 
     {
          fileManager.StartNewFile(filePath);

#>
// the content of the validator class
public partial class <#=code.Escape(entity)#>
{
    public bool ValidateModel()
    {
    // enter checkmethods here!!! again
    return true;
    }
}
<#          
    }           
}

fileManager.Process(true);

#>

5 个答案:

答案 0 :(得分:5)

我处于完全相同的情况。我想为数据注释生成好友类。我不想将数据放入edmx文件并更改我的模板以根据edmx数据添加正确的注释。这将花费太长时间。最简单的解决方案是生成一个伙伴类并设置它,使其不会每次都重新生成。在这种情况下,效率比应该始终重新生成T4类的约定更重要。

Dane Morgridge想出了一个聪明的方法来做到这一点。他检查文件是否已经存在。如果确实如此,他会将其读入并按原样将其写回。如果没有,他会渲染他的模板。查看DbContext Templates \ IRepository.tt。 https://github.com/danemorgridge/efrepo

以下是相关章节。

string OutputFile(string filename)
{
    using(StreamReader sr = new StreamReader(Path.Combine(GetCurrentDirectory(),filename)))
    {
        string contents = sr.ReadToEnd();
        return contents;
    }
}

if(!DoesFileExist(entity.Name + "Repository.cs"))
{
    fileManager.StartNewFile(entity.Name + "Repository.cs");
}
else
{
    fileManager.StartNewFile(entity.Name + "Repository.cs");
    this.Write(OutputFile(entity.Name + "Repository.cs"));
}

答案 1 :(得分:2)

有点晚了,但值得一提......如果你正在使用T4Toolbox,你可以告诉引擎如果触发了一代并且文件已经存在,就不要删除生成的文件:

template.Output.PreserveExistingFile = true;

http://t4toolbox.codeplex.com

答案 2 :(得分:1)

不,你不能。每次触发T4模板时都会生成代码并执行代码。在此之前,所有文件都会被删除。但那你的问题是什么?您应该将自定义代码放在partials中,以便重新生成其他部分get并不重要。

答案 3 :(得分:0)

重新创建文件有什么问题? T4生成代码,您不应该触摸生成的代码。如果你只使用T4模板来创建一些名称错误的文件。您可以创建真实的T4模板,它也会生成文件的内容,或者您​​不应该使用T4模板并手动创建文件。

答案 4 :(得分:0)

对于创建元数据,服务和ViewModel类(我希望能够修改)的T4模板,我希望能够将新模板与现有模板合并,并为新实体创建任何新模板,所以我在调用fileManager.StartNewFile ...

之前创建了一个文件备份(.BAK)
    foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
    {
        var outputPath = Path.GetDirectoryName(Host.TemplateFile);
        var outputFile = entity.Name + ".ViewModel.cs";
        var fileName = Path.Combine(outputPath, outputFile);
        if (File.Exists(fileName))
        {
            var newName = fileName + ".BAK";
            File.Move(fileName, newName);
        }

        fileManager.StartNewFile(outputFile);

然后在fileManager.Process之后我使用SourceGear的DiffMerge合并.BAK文件和新文件......

    fileManager.Process();

    System.Diagnostics.Process p = new System.Diagnostics.Process();

    foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
    {

        var outputPath = Path.GetDirectoryName(Host.TemplateFile);
        var outputFile = entity.Name + ".ViewModel.cs";
        var fileName = Path.Combine(outputPath, outputFile);
        var newName = fileName + ".BAK";
        if (File.Exists(newName))
        {
            String s = String.Format("-m -nosplash \"{0}\" \"{1}\" \"{2}\"", fileName, fileName, newName);
            p.StartInfo.Arguments = s;
            p.StartInfo.FileName = "C:\\Program Files (x86)\\SourceGear\\DiffMerge\\DiffMerge.exe";
            p.StartInfo.Verb = "Open";
            p.Start();
            p.WaitForExit();

            File.Delete(newName);
        }

    }

效果很好,因为DiffMerge是一个GUI应用程序,我可以在保存之前处理冲突等。