Как передать строковый параметр в шаблон t4

Привет, Я пытаюсь найти способ передать нормальную строку в качестве параметра в текстовый шаблон.

Это мой код шаблона, если кто-то может сказать мне, что мне нужно будет написать в С#, чтобы передать мои параметры и создать файл класса. Это было бы очень полезно, спасибо.

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ parameter name="namespacename" type="System.String" #>
<#@ parameter name="classname" type="System.String" #>
<#
this.OutputInfo.File(this.classname);
#>
namespace <#= this.namespacename #>
{
    using System;
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Xml; 

    /// <summary>
    /// This class describes the data layer related to <#= this.classname #>.
    /// </summary>
    /// <history>
    ///   <change author=`Auto Generated` date=<#= DateTime.Now.ToString("dd/MM/yyyy") #>>Original Version</change>
    /// </history>
    public partial class <#= this.classname #> : DataObject
    {
        #region constructor

        /// <summary>
        /// A constructor which allows the base constructor to attempt to extract the connection string from the config file.
        /// </summary>
        public <#= this.classname #>() : base() {}

        /// <summary>
        /// A constructor which delegates to the base constructor to enable use of connection string.
        /// </summary>
        /// <param name='connectionstring`></param>
        public <#= this.classname #>(string connectionstring) : base(connectionstring) {}

        #endregion
    }
}

Ответ 1

Ниже приведен один из способов передачи параметров:

  • Вам нужно создать TextTemplatingSession.
  • Установите словарь сеанса для параметров.
  • Обработать шаблон, используя этот сеанс.

Пример кода (замените ResolvePath на местоположение вашего файла tt):

<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<# 
string templateFile = this.Host.ResolvePath("ClassGeneration.tt");
string templateContent = File.ReadAllText(templateFile);

TextTemplatingSession session = new TextTemplatingSession();
session["namespacename"] = "MyNamespace1";
session["classname"] = "MyClassName";

var sessionHost = (ITextTemplatingSessionHost) this.Host;
sessionHost.Session = session;

Engine engine = new Engine();
string generatedContent = engine.ProcessTemplate(templateContent, this.Host);

this.Write(generatedContent);  #>

Я видел этот пример в блоге Олега Сыха, который является отличным ресурсом для t4.

Ответ 2

Это трехлетний вопрос, и я не знаю, насколько расширились библиотеки шаблонов, и если мое решение проблемы относится к более старым версиям Visual Studio и/или .NET и т.д. Я в настоящее время использую Visual Studio 2015 и .NET 4.6.1.

Резюме

Используйте блок управления функциями класса, чтобы объявить публичные члены сгенерированного класса вашего шаблона и обратиться к этим открытым членам в тексте вашего шаблона.

Пример

В проекте С# выберите Добавить новый элемент > Шаблон текста выполнения > "Salutation.tt". Вы получаете новый .tt файл со следующими объявлениями по умолчанию:

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

Ниже объявления введите текст вашего шаблона:

My name is <#= Name #>.
<# if (RevealAge) { #>
I am <#= Age #> years old.
<# } #>

В конце файла .tt добавьте свои параметры в качестве публичных членов класса внутри "блока управления функциями класса". Этот блок должен перейти в конец файла.

<#+
public string Name { get; set; }
public int Age { get; set; }
public bool RevealAge = false;
#>

Затем, например, в Консольном приложении вы можете использовать свой шаблон следующим образом:

Console.Write(new Salutation
{
    Name = "Alice",
    Age = 35,
    RevealAge = false
}.TransformText());

Console.Write(new Salutation
{
    Name = "Bob",
    Age = 38,
    RevealAge = true
}.TransformText());

И получите следующий результат:

My name is Alice.
My name is Bob.
I am 38 years old.
Press any key to continue . . .

Дополнительные сведения о синтаксисе T4 см. в статье MSDN Написание текстового шаблона T4.

Ответ 3

Также возможно ввести параметры в содержимое шаблона перед его обработкой. Для этого добавьте <##> в свой шаблон в качестве заполнителя для внедрения кода.

GenericClass.ttinclude:

 <#@template language="C#" #> <##> namespace <#= Namespace #> { public class <#= ClassName #>: IGeneric<<#= TypeParameter #>> { public <#= TypeParameter #> ReturnResult() => 1 + 3; } } <#+ public string ClassName { get; set; } public string Namespace { get; set; } public string TypeParameter { get; set; } #>

Затем добавьте общий шаблон для импорта других шаблонов (Generator.ttinclude):

 <#@import namespace="System.IO" #> <#@import namespace="System.Text" #> <#@import namespace="System.Collections.Generic" #> <#@import namespace="Microsoft.VisualStudio.TextTemplating" #> <#+ public const string ParametersInjectionPattern = "<" + "#" + "#" + ">"; public void Generate(string baseTemplatePath, IDictionary<string, string> parameters) { var template = File.ReadAllText(this.Host.ResolvePath(baseTemplatePath)); template = template.Replace(ParametersInjectionPattern, GenerateParametersAssignmentControlBlock(parameters)); this.Write(new Engine().ProcessTemplate(template, this.Host).Trim()); } public string GenerateParametersAssignmentControlBlock(IDictionary<string, string> parameters) { var sb = new StringBuilder(); sb.Append('<').Append('#').Append(' '); foreach (var parameter in parameters) sb.Append($"{parameter.Key} = {parameter.Value};"); sb.Append(' ').Append('#').Append('>'); return sb.ToString(); } public string SurroundWithQuotes(string str) { return $"\"{str}\""; } public string GetTemplateName() { return Path.GetFileNameWithoutExtension(this.Host.TemplateFile).Replace(".Generated", ""); } #>

А затем используйте его в любом конкретном шаблоне, где вы можете просто передать необходимые параметры (UInt64Class.Generated.tt):

<#@ template hostspecific="true" language="C#" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#@ include file="Generator.ttinclude" #>
<#
    var parameters = new Dictionary<string, string>()
    {
        { "Namespace", SurroundWithQuotes("T4GenericsExample") },
        { "ClassName", SurroundWithQuotes(GetTemplateName()) },
        { "TypeParameter", SurroundWithQuotes("System.UInt64") }
    };

    Generate("GenericClass.ttinclude", parameters);
#>

Полный пример можно найти по адресу https://github.com/Konard/T4GenericsExample.