Вызов абстрактного и производного шаблона tt в расширении VS - PullRequest
0 голосов
/ 17 сентября 2018

Я работаю над расширением для VS. Он должен отображать объект базы данных через шаблоны TT. Шаблоны могут быть сделаны пользователями расширения. Единственное, что должны наследовать абстрактный шаблон, который является частью расширения. Я нашел рекомендацию в документации Microsoft для вызова преобразования в расширении VS следующим образом: Вызов преобразования текста в расширении VS Для фиктивного шаблона это работает нормально, например:

<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>

<#
Generate(new List<string> {"AAA","BBB","CCC"},  "666");
#>
<#+ 
public void Generate(List<string> inputList, string tableName)
{
#>
using System;
using System.Collections.Generic;
using System.Data;
using System.Runtime.Serialization;

namespace BBB 

public class <#= tableName #>
{
    <#+
    foreach(var t in inputList)
    {
    #>
        /// <summary>
        /// <#= t #>
        /// </summary>
    <#+
    }
    #>
}
<#+
}
#>

И код:

Generate("..\\..\\Templates\\TextTemplate.tt");

public void Generate(string filePath)
    {
        IServiceProvider serviceProvider = ServiceProvider;
        ITextTemplating t4 = serviceProvider.GetService(typeof(STextTemplating)) as ITextTemplating;
        T4Callback cb = new T4Callback();
        string result = t4.ProcessTemplate(filePath, File.ReadAllText(filePath), cb);
        string resultFileName = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath)) + "_gen" + cb.fileExtension;
        File.WriteAllText(resultFileName, result, cb.outputEncoding);
    }


public class T4Callback : ITextTemplatingCallback
{
    public List<string> errorMessages = new List<string>();
    public string fileExtension = ".cs";
    public Encoding outputEncoding = Encoding.UTF8;

    public void ErrorCallback(bool warning, string message, int line, int column)
    { errorMessages.Add(message); }

    public void SetFileExtension(string extension)
    { fileExtension = extension; }

    public void SetOutputEncoding(Encoding encoding, bool fromOutputDirective)
    { outputEncoding = encoding; }
}

Но это не работает с абстрактным шаблоном. Если у меня есть абстрактный шаблон:

<#@ template language="C#" #>

<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>

<#@ parameter type="System.String" name="FakeIn" #> 

<#   
this.PushIndent("  ");  

//Generate method
Generate(InputData); 

//Save method
SaveOutput(OutputFileName);

this.PopIndent();  
#>  

<#+ 
#region Properties
public string OutputFileName { get; set; }
public InPutClass InputData { get; set; }
#endregion

#region Override method
protected virtual void Generate(InPutClass input) { }
#endregion

#region Non-Override method
protected void SaveOutput(string outputFileName) 
{
    string outputFilePath = Path.Combine(outputFileName);
    File.WriteAllText(outputFilePath, this.GenerationEnvironment.ToString()); 
    this.GenerationEnvironment.Remove(0, this.GenerationEnvironment.Length);
}
#endregion

#region Data classes
public class InPutClass
{
    public List<string> InputList { get; set; }
    public string InputTableName { get; set; }
}
#endregion
#>

и вывел один такой:

<#@ template language="C#" inherits="AbstractTemplate" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>

<#
InputData = new InPutClass{ InputList = new List<string>{"AAA","BBB","CCC"}, InputTableName = "abc" };
OutputFileName = "..\\..\\Templates\\file2.cs";
base.TransformText();  
#>

<#+ 
protected override void Generate(InPutClass input)
{
#>
using System;
using System.Collections.Generic;
using System.Data;
using System.Runtime.Serialization;
using ABEL.CORE.TypeComponents;
using ABEL.DAL.Attributes;
using Protos.Data;

namespace BBB 

public class <#= input.InputTableName #>
{
    <#+
    foreach(var t in input.InputList)
    {
    #>
        /// <summary>
        /// <#= t #>
        /// </summary>
    <#+
    }
    #>
}
<#+
}
#>

Если я вызываю метод Generate, результатом будет:

ErrorGeneratingOutput

  • Преобразование компиляции: не удалось найти имя типа или пространства имен 'AbstractTemplate' (отсутствует директива using или ссылка на сборку?)
  • Преобразование компиляции: не удалось найти имя типа или пространства имен 'InPutClass' (отсутствует директива using или ссылка на сборку?)
  • Преобразование компиляции: 'GeneratedTextTransformation.TransformText ()': не найден подходящий метод для переопределения
  • Преобразование компиляции: 'GeneratedTextTransformation.Generate (InPutClass)': не найден подходящий метод для переопределения
  • Преобразование компиляции: «GeneratedTextTransformation» не содержит определения для «Write», и не найдено никакого метода расширения «Write», принимающего первый аргумент типа «GeneratedTextTransformation» (вы пропустили директиву using или ссылку на сборку?)
  • Компиляция преобразования: имя 'InputData' не существует в текущем контексте
  • Преобразование компиляции: не удалось найти имя типа или пространства имен 'InPutClass' (отсутствует директива using или ссылка на сборку?)
  • Компиляция преобразования: имя 'OutputFileName' не существует в текущем контексте
  • Преобразование компиляции: «GeneratedTextTransformation» не содержит определения «Write», и не найдено никакого метода расширения «Write», принимающего первый аргумент типа «GeneratedTextTransformation» (вы пропустили директиву using или ссылку на сборку?)
  • Преобразование компиляции: «GeneratedTextTransformation» не содержит определения для «GenerationEnvironment», и метод расширения «GenerationEnvironment», принимающий первый аргумент типа «GeneratedTextTransformation», не найден (вам не хватает директивы using или ссылки на сборку?)
  • Преобразование компиляции: «GeneratedTextTransformation» не содержит определения для «GenerationEnvironment», и не удалось найти метод расширения «GenerationEnvironment», принимающий первый аргумент типа «GeneratedTextTransformation» (вам не хватает директивы using или ссылки на сборку?)
  • Преобразование компиляции: «GeneratedTextTransformation» не содержит определения для «Write», и не найдено никакого метода расширения «Write», принимающего первый аргумент типа «GeneratedTextTransformation» (вы пропустили директиву using или ссылку на сборку?)
  • Преобразование компиляции: «GeneratedTextTransformation» не содержит определения для «Write», и метод расширения «Write», принимающий первый аргумент типа «GeneratedTextTransformation», не найден (вы пропустили директиву using или ссылку на сборку?)
  • Преобразование компиляции: «GeneratedTextTransformation» не содержит определения «Write», и не найдено никакого метода расширения «Write», принимающего первый аргумент типа «GeneratedTextTransformation» (вы пропустили директиву using или ссылку на сборку?)
  • Преобразование компиляции: «GeneratedTextTransformation» не содержит определения «Write», и не найдено никакого метода расширения «Write», принимающего первый аргумент типа «GeneratedTextTransformation» (вы пропустили директиву using или ссылку на сборку?)
  • Преобразование компиляции: «GeneratedTextTransformation» не содержит определения для «Write», и метод расширения «Write», принимающий первый аргумент типа «GeneratedTextTransformation», не найден (вы пропустили директиву using или ссылку на сборку?)
  • Преобразование компиляции: «GeneratedTextTransformation» не содержит определения для «Write», и не найдено никакого метода расширения «Write», принимающего первый аргумент типа «GeneratedTextTransformation» (если вы пропустили директиву using или ссылку на сборку?)
  • Преобразование компиляции: 'GeneratedTextTransformation' не содержит определения для 'Write', и не найдено никакого метода расширения 'Write', принимающего первый аргумент типа 'GeneratedTextTransformation' (вы пропустили директиву using илиссылка на сборку?)

Так что для меня это выглядит так: шаблоны ничего не знают о себе.Потому что, когда я использую их как часть решения и вызываю просто классический шаблон template.TransformText ();все отлично.

Я также пробую некоторую комбинацию PreprocessingTemplate, например:

   GenerateAbstract("\\..\\..\\Templates2\\DerivedTemplate2.tt");
   public void GenerateAbstract(string filePath)
    {
        IServiceProvider serviceProvider = ServiceProvider;
        ITextTemplating t4 = serviceProvider.GetService(typeof(STextTemplating)) as ITextTemplating;

        T4Callback cb = new T4Callback();
        string[] reference;
        string abstractTemplatePath = "..\\..\\Templates2\\AbstractTemplate.tt";

        string abstractTemplatePreprocessing = t4.PreprocessTemplate(abstractTemplatePath, File.ReadAllText(abstractTemplatePath), cb, "AbstractTemplate", "AbstractTemplating.Templates2", out reference);
        string derived2TemplatePreprocessing = t4.PreprocessTemplate(filePath, File.ReadAllText(filePath), cb, "DerivedTemplate2", "AbstractTemplating.Templates2", out reference);

        File.WriteAllText(Path.Combine("..\\..\\Templates2", "AbstractTemplate.cs"), abstractTemplatePreprocessing, cb.outputEncoding);
        File.WriteAllText(Path.Combine("..\\..\\Templates2", "DerivedTemplate2.cs"), derived2TemplatePreprocessing, cb.outputEncoding);

        string result = t4.ProcessTemplate("..\\..\\Templates2\\AbstractTemplate.cs", derived2TemplatePreprocessing, cb);

        string resultFileName = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath)) + "_gen" + cb.fileExtension;
        // Write the processed output to file:
        File.WriteAllText(resultFileName, result, cb.outputEncoding);
        // Append any error messages:
        if (cb.errorMessages.Count > 0)
        {
            File.AppendAllLines(resultFileName, cb.errorMessages);
        }
    }

Но в этом случае это код результата C # для DerivedTemplate2: AbstractTemplate, что-то вроде того, когда шаблон является частью решения и решенияпостроен

Итак, наконец, мой вопрос можно назвать абстрактным и производным шаблоном так?И если есть, не могли бы вы привести пример, как этого добиться.Спасибо

1 Ответ

0 голосов
/ 17 сентября 2018

Это только мнение, но по вашей описанной теме:

1) не скрывать шаблон от пользователя (поместить его в решение вместе с сгенерированным кодом) - метод, который делают VS MVC-Entity-Extensionэто - наоборот - но MS в этом случае ошибается (и низкая популярность генерации кода в мире MS свидетельствует об этом).Если вам нужно сгенерировать 100 файлов, сгенерируйте также 100 шаблонов.Но лучше один шаблон, который генерирует сотни классов в одном файле.

2) не смешивает генерацию кода и наследование реализации - они ортогональны друг другу.Во-первых, для публикации «всего» для пользователя в форме, в которой пользователь может изменить «все», во-вторых, для скрытия деталей (зачем скрывать детали, если вы хотите предоставить пользователю функциональность «изменить все»)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...