Шаблон T4 и параметры времени выполнения - PullRequest
8 голосов
/ 09 декабря 2010

Я создаю плагин в VS 2010, и я застреваю в поколении T4.Прямо сейчас я реализовал (как MSDN предлагает) собственный хост T4 для генерации результатов T4 и использую его следующим образом:

        const string content = @"c:\Simple.tt";
        var engine = new Engine();
        var host = new MyTemplateHost();            
        var result = engine.ProcessTemplate(File.ReadAllText(content), host);
        foreach (CompilerError error in host.Errors)
        {
            Console.WriteLine(error.ErrorText);
        }

Это работает, пока я не передам параметр в шаблоне.Как только я создаю параметр в файле .tt, хост начинает волноваться, говоря, что не знает, как его разрешить.Я видел, что вы можете использовать TemplateSession для этого, но я не понял, как передать его на мой хост?Есть ли лучший способ генерации кода из .tt с использованием C # и передачи параметров во время выполнения?Может быть, я на неправильном пути.

Ответы [ 6 ]

12 голосов
/ 10 декабря 2010

В Visual Studio 2010 механизм шаблонов T4 был радикально изменен.Теперь вы можете напрямую запустить файл шаблона и передать ему любой параметр нужного вам типа.

        var template = Activator.CreateInstance<SimpleTemplate>();
        var session = new TextTemplatingSession();
        session["namespacename"] = "MyNamespace";
        session["classname"] = "MyClass";
        var properties = new List<CustomProperty>
        {
           new CustomProperty{ Name = "FirstProperty", ValueType = typeof(Int32) }
        };
        session["properties"] = properties;
        template.Session = session;
        template.Initialize();

Этот оператор обработает следующий шаблон:

<#@ template language="C#" debug="true"  #>
<#@ output extension=".cs" #>
<#@ assembly name="System.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="SampleDomain.Entities" #>
<#@ parameter name="namespacename" type="System.String" #>
<#@ parameter name="classname" type="System.String" #>
<#@ parameter name="properties" type="System.Collections.Generic.List<CustomProperty>" #>

using System;
using System.Collections.Generic;
using SampleDomain.Entities;

namespace <#= this.namespacename #>
{
public class <#= this.classname #>

Так что, честно говоря, хозяин больше не нужен ...

7 голосов
/ 11 января 2012

Добавьте и внедрите ITextTemplatingSessionHost на свой пользовательский хост.Простая реализация ITextTemplatingEngineHost не обеспечит вам поддержку сеанса.

 [Serializable()]
    public class CustomCmdLineHost : ITextTemplatingEngineHost,ITextTemplatingSessionHost
    {

        ITextTemplatingSession session = new TextTemplatingSession();

        public ITextTemplatingSession CreateSession()
        {
            return session;
        }

        public ITextTemplatingSession Session
        {
            get
            {
                return session;
            }
            set
            {
                session = value;
            }
        }
7 голосов
/ 13 января 2011

Если вы создаете надстройку для VS, вам, вероятно, не нужен пользовательский хост, но вместо этого вы можете использовать встроенный хост VS через сервисный интерфейс.

Извлечь ITextTemplating в качестве основного API службы, который вы можете получить, приведя ваш объект DTE к IServiceProvider, затем вызвав GetService (typeof (STextTemplating)) *

Чтобы передать параметры, вы можете затем передать объект ITextTemplating в сторону ITextTemplatingSessionHost и задайте для свойства Session реализацию ITextTemplatingSession .Сессия по сути является просто сериализуемым пакетом свойств.Существует тривиальный вариант: TextTemplatingSession .

4 голосов
/ 13 апреля 2016

Использование шаблонов T4 для генерации во время выполнения

  1. Вы выбираете этот метод, если вам нужно генерировать код во время выполнения.Например, вы хотите сгенерировать объект страницы с помощью Selenium.

    enter image description here

  2. Создайте папку в своем решении, назовите ее Templates (хорошее название для шаблонов T4).

  3. Затем добавьте новый элемент типа T4, затем выберите текстовый шаблон времени выполнения .... Мы назвали наш шаблон MyNodeName.tt, который показан на изображении выше.

  4. Добавьте код, как показано ниже, верхняя часть была вставлена ​​Visual Studio ...

Add Code

Вы можете видеть, что мы хотим передать имена пространств имен и классов (это разметка Model.NameSpaceName и Model.ClassName, показанная выше.

Сложная задача - научиться передавать параметры...

Создать новый класс CS с частичным именем в имени файла.

Partial File Name

Но в классе неназовите его MyNodeNamePartial назовите его MyNodeName следующим образом:

   public partial class MyNodeName
    {
       public MyNodeNameModel Model { get; set; }
    }

Это то же имя, что и у файла TT. (MyNodeName), который создает собственный частичный класс. Но теперь обратите внимание, что у нас есть значение с именем MODEL этого классавведите ..

   public class MyNodeNameModel
    {
        public MyNodeNameModel()
        {
            ClassName = "Test";
        }
        public string ClassName { get; set; }
        public string NameSpaceName { get; set; }
    }

Класс модели содержит ClassName и NameSpaceName и все остальное, что выМуравей, чтобы «вставить» в шаблон.

Ключ к этой работе, как показано , заключается в том, что был использован текстовый шаблон времени выполнения!Если вы используете текстовый шаблон, независимо от того, что вы делаете, вы увидите ошибки, похожие на «Модель не найдена» или другие неоднозначные проблемы.

Советы по отладке: «Модель не может быть найдена» - это код генерации T4, сообщающий вам, что в вашем частичном классе с переменной MODEL он не может ее найти!Проверьте и ваш частичный тип, и тип модели, чтобы убедиться, что они находятся в том же пространстве имен, что и любое другое пространство имен нормального класса, если бы оно было создано в этой папке.

1 голос
/ 11 июля 2014

Посмотрите на Справочник MSDN (Раздел «Передача параметров в конструкторе»).

Подведем итог:

Создайте частичный класс с тем же именем, что и ваш файл TT.

partial class MyWebPage
{
    private MyData m_data;
    public MyWebPage(MyData data) { this.m_data = data; }}
}

Тогда просто передайте свои параметры в конструктор класса

MyWebPage page = new MyWebPage(data);
String pageContent = page.TransformText();
0 голосов
/ 13 июня 2011

Разобрался. Для интересующихся см. Следующее:

http://www.olegsych.com/2009/09/t4-preprocessed-text-templates/

...