2011-05-09 6 views
6

Je souhaite créer pour chaque entité de mon modèle edmx un fichier de classe distinct appelé {0} Validator.cs (ne se soucie pas de son contenu pour le moment).Empêcher le modèle T4 de supprimer des fichiers existants

Cela semble fonctionner, mais je ne peux pas le faire pour empêcher mon modèle T4 de supprimer tous mes fichiers en premier. Comment puis-je me débarrasser de ce comportement? Ce que j'ai découvert est que si j'appelle fileManager.Process (true), tous les fichiers sous mon fichier validator.tt seront recréés (et je ne veux pas cela).

Des idées s'il vous plaît? Merci!

<#@ 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 [email protected]"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); 

#> 

Répondre

1

Non, vous ne pouvez pas. Les T4 Templates génèrent le code chaque fois qu'ils sont déclenchés et exécutent le code. Et avant cela, tous les fichiers sont supprimés. Mais quel est votre problème avec ça? Votre code personnalisé doit être placé dans les partiels, donc cela n'a pas d'importance si l'autre get partiel est régénéré.

+0

Merci pour votre réponse.Bien sûr, les classes personnalisées sont dans des classes partielles séparées, mais les partiels doivent être créés chaque fois que le modèle t4 est exécuté et si edmx a été mis à jour par l'utilisateur (une nouvelle table a été ajoutée), les classes existantes doivent être intactes. Une nouvelle classe de validateurs pour le tableau de données nouvellement ajouté doit être générée (et non fabriquée à la main par l'utilisateur). C'est ce que je veux avoir, mais peut-être que fournir un extrait ou un modèle prend moins de temps à cette fin ;-). Merci! – HarryK

+0

Oui, cela semble être la meilleure solution pour vos besoins, parce que vous voulez être en mesure de dire à T4 d'épargner les fichiers déjà générés. – sra

+0

Salut Sra, je pense que je vais le faire d'une manière snippet/template - je n'ai pas le temps de perdre :-). Merci pour vos réponses! – HarryK

0

Qu'est-ce qui ne va pas avec la recréation de fichiers? T4 génère le code et vous ne devez pas toucher le code généré. Si vous utilisez le modèle T4 juste pour créer des fichiers avec certains noms, vous l'utilisez mal. Vous pouvez soit créer un vrai template T4 qui générera aussi le contenu de votre fichier, soit vous ne devez pas utiliser le template T4 et créer des fichiers manuellement.

+0

Salut, merci pour votre réponse - je garderai cela à l'esprit. Rien ne va pas avec la récréation sauf: Je ne veux pas ça. Si vous ne vous souciez pas du contenu du fichier (bien sûr, le fichier aurait une logique générée) le défi pour moi n'était pas simplement de créer des fichiers, le défi était: PUIS-je empêcher les fichiers d'être régénérés à chaque fois si Je ne veux pas ça? Je suppose que je ferais mieux d'aller avec des extraits et des modèles et MAYBE T4 est - et vous pourriez avoir raison - pas le bon outil pour ce but particulier. Merci! – HarryK

5

Je suis exactement dans la même situation. Je veux générer des classes de contacts pour l'annotation de données. Je ne veux pas mettre de données dans le fichier edmx et modifier mes modèles pour ajouter les annotations correctes basées sur les données edmx. Cela prendrait trop de temps. La solution la plus simple consiste à générer une classe de buddy et à la configurer pour qu'elle ne se régénère pas à chaque fois. Dans ce cas, l'efficacité est plus importante que la convention selon laquelle les classes T4 doivent toujours être régénérées. Dane Morgridge a trouvé une façon intelligente de le faire. Il vérifie pour voir si le fichier existe déjà. Si c'est le cas, il le lit et le réécrit tel qu'il était. Si ce n'est pas le cas, il rend son modèle. Découvrez DbContext Templates \ IRepository.tt. https://github.com/danemorgridge/efrepo

Voici les sections pertinentes.

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

Pour les modèles T4 qui créent des métadonnées, des services et des classes ViewModel (que je veux être en mesure de modifier), je voulais la possibilité de fusionner les nouveaux modèles avec ceux qui existent déjà, ainsi que de créer des nouveaux pour les nouvelles entités, donc je crée une sauvegarde du fichier (BAK) avant d'appeler 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); 

puis après fileManager.Process je fusionner le fichier BAK et le nouveau à l'aide de DiffMerge SourceGear ...

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

    } 

Fonctionne plutôt bien, et comme DiffMerge est une application graphique, je peux gérer les conflits, etc. avant de sauvegarder.

1

Un peu en retard, mais pour ce que ça vaut ... Si que vous utilisez T4Toolbox vous pouvez indiquer au moteur de ne pas supprimer les fichiers générés si une génération est déclenchée et que le fichier existe déjà:

template.Output.PreserveExistingFile = true; 

http://t4toolbox.codeplex.com

Questions connexes