Prevent deletion of T4 template from existing files

I want to create a separate class file for each object in my edmx model with the name {0} Validator.cs (now it is not interested in its contents).

This seems to work, but I can't solve it to prevent my T4 template from deleting all my files. How can I get rid of this behavior?

I found out that if I call fileManager.Process (true), all the files under my validator.tt file will be recreated (and I don't want this).

Any ideas please? Thanks!

<#@ 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); #> 
+6
source share
5 answers

I am in the same situation. I want to generate buddy classes to annotate data. I do not want to put the data in the edmx file and modify my templates to add the correct annotations based on the edmx data. It takes too long. The simplest solution is to create a buddy class and set it so that it does not recover every time. In this case, efficiency is more important than the agreement that T4 classes should always be restored.

Dane Morgrides has found a smart way to do this. It checks if the file already exists. If he does, he reads it and writes back the way it was. If it does not, he makes his own template. Check out the DbContext \ IRepository.tt templates. https://github.com/danemorgridge/efrepo

Here are the relevant sections.

 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")); } 
+5
source

No, you can’t. T4 templates generate code every time you run and execute code. And before that, all files are deleted. But what is the problem? You custom code should be placed in partial, so it does not matter if another partial is regenerated.

+1
source

A little late, but what is it worth ... If you use T4Toolbox, you can tell the engine not to delete the generated files if the generation is running and the file already exists:

 template.Output.PreserveExistingFile = true; 

http://t4toolbox.codeplex.com

+1
source

What happened to reconstructing files? T4 generates code, and you should not touch the generated code. If you use the T4 template only to create files with some names, you are using it incorrectly. You can create a real T4 template that will also generate the contents of your file, or you should not use the T4 template and create files manually.

0
source

For T4 templates that create metadata, service, and ViewModel classes (which I want to change), I need the ability to combine new templates with existing ones, as well as create new ones for new objects, so I back up the file (.BAK) before calling fileManager. StartNewFile ...

  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); 

and then after fileManager.Process I merge the .BAK file and the new one using SourceGear DiffMerge ...

  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); } } 

It works very well, and since DiffMerge is a GUI, I can handle conflicts, etc. before saving.

0
source

Source: https://habr.com/ru/post/887645/


All Articles