Запрет шаблона T4 от удаления существующих файлов - PullRequest
6 голосов
/ 09 мая 2011

Я хочу создать для каждой сущности в моей edmx-модели отдельный файл класса с именем {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 ]

5 голосов
/ 10 ноября 2011

Я в точно такой же ситуации.Я хочу создавать приятельские классы для аннотации данных.Я не хочу помещать данные в файл edmx и изменять мои шаблоны, чтобы добавить правильные аннотации на основе данных edmx.Это займет слишком много времени.Самое простое решение - создать класс партнера и установить его так, чтобы он не обновлялся каждый раз.В этом случае эффективность важнее, чем соглашение о том, что классы T4 всегда должны быть восстановлены.

Дейн Моргридж нашел умный способ сделать это.Он проверяет, существует ли файл.Если он это делает, он читает и записывает обратно, как это было.Если это не так, он отображает свой шаблон.Проверьте шаблоны DbContext \ 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"));
}
2 голосов
/ 16 марта 2013

Немного поздно, но для чего стоит ... Если вы используете T4Toolbox, вы можете сказать движку не удалять сгенерированные файлы, если генерация запущена и файл уже существует:

template.Output.PreserveExistingFile = true;

http://t4toolbox.codeplex.com

1 голос
/ 09 мая 2011

Нет, вы не можете. Шаблоны T4 генерируют код каждый раз, когда они запускаются и выполняют код. А до этого все файлы удаляются. Но в чем твоя проблема? Ваш пользовательский код должен быть помещен в партиалы, поэтому не имеет значения, будет ли восстановлен другой частичный get.

0 голосов
/ 30 ноября 2011

Для шаблонов T4, которые создают классы Metadata, Service и ViewModel (которые я хочу изменить), я хотел иметь возможность объединять новые шаблоны с существующими, а также создавать любые новые для новых сущностей поэтому я создаю резервную копию файла (.BAK) перед вызовом 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);

, а затем после fileManager.Process я объединяю файл .BAK и новый, используя 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);
        }

    }

Работает довольно хорошо, и, поскольку DiffMerge - приложение с графическим интерфейсом, я могу обрабатывать конфликты и т. Д. Перед сохранением.

0 голосов
/ 10 мая 2011

Что не так с воссозданием файлов? T4 генерирует код, и вы не должны касаться сгенерированного кода. Если вы используете шаблон T4 только для создания файлов с некоторыми именами, вы используете его неправильно. Вы можете либо создать настоящий шаблон T4, который будет генерировать содержимое вашего файла, либо вам не следует использовать шаблон T4 и создавать файлы вручную.

...