передать объект в шаблон T4 - PullRequest
5 голосов
/ 31 мая 2011

У меня есть объект u1 типа User класса.У пользователя есть атрибут name.Как я могу передать u1 в шаблон T4?Я пытаюсь сделать что-то очень простое:

User u1 = new User("John"); 


Шаблон скрипта:

Hello <# u1.Name #>

Ответы [ 5 ]

3 голосов
/ 10 сентября 2011

Мы сделали что-то похожее на это. Наше решение имеет следующие элементы:

  • Пользовательский хост
  • Пользовательский базовый класс шаблона (свойство «наследует» директивы шаблона)
  • Шаблоны, специфичные для хоста (свойство hostspecific для директивы шаблона)

Пользовательский хост агрегируется объектом, для которого сам трафарет хочет вызывать методы.

interface ICallbackInterface
{
    void CallbackFxn();
}

[Serializable]
public class MyCustomHost : ITextTemplatingEngineHost, ITextTemplatingSessionHost, IStencilFileRecordManagement
{

    private ICallbackInterface callback = null;
    public MyCustomHost(ICallbackInterface cb)
    {
        callback = cb;
    }

    public void CallbackFxn()
    {
        callback.CallbackFxn();
    }
}

public abstract class MyTemplateBase : TextTransformation
{
    public virtual MyCustomHost CustomHost
    {
        get
        {
            dynamic metame = this;
            MyCustomHost rval = null;
            try
            {
                /// <summary>
                /// The "Host" property will be added to the generated class by the T4 environment whenever a 
                /// "hostspecific" template is processed. 
                /// </summary>
                rval = metame.Host as MyCustomHost;
            }
            catch (RuntimeBinderException e)
            {
                logger.ErrorException(
                    "Received the following exception while processing a stencil template", e);

            }
            return rval;
        }
    }
}

Теперь в любом из наших шаблонов мы можем вызывать методы для объекта, которые фактически начали обработку, используя пользовательское свойство хоста, например:

<# CustomHost.CallbackFxn(); #>

Кроме того, мы не используем T4 в VS или отдельный исполняемый файл - мы ссылаемся на сборки Microsoft.VisualStudio.TextTemplating.10.0 и Microsoft.VisualStudio.TextTemplating.Interfaces.10.0.

EDIT

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

using Microsoft.VisualStudio.TextTemplating;

class UserPluginWorkflowComponent : ICallbackInterface
{
    public void CallbackFxn()
    {
        // invoked by user plugin
    }

    public void ExecuteUserPlugin()
    {
        MyCustomHost host = new MyCustomHost(this);
        host.TemplateFileValue = "UserPluginTemplateFilename";
        Engine engine = new Engine();
        string pluginResult = engine.ProcessTemplate(
            userPluginTemplateFileContents, 
            host);            
        if (!host.Errors.HasErrors)
        {
            // use pluginResult in some meaningful way
        }
    }
}
2 голосов
/ 31 мая 2011

Вы хотите использовать его в своем шаблоне? Затем вам нужно добавить ссылку на сборку, содержащую тип. Вы не можете просто передать существующую ссылку на движок T4, если не разместите его самим каким-нибудь весьма неортодоксальным способом (я никогда не видел, чтобы кто-нибудь пытался это сделать). И даже если бы вы зашли так далеко и сделали это, как бы вы это запустили? Откуда взялась эта ссылка?

Использовать тип из шаблона T4 так же просто, как добавить ссылку или скопировать / вставить ее в заглушку класса <#+ /*stuff goes here*/ #>.

1 голос
/ 16 июня 2011

Предполагая, что вы хотите иметь код в каком-либо приложении или инструменте, который в конечном итоге запускает шаблон, а затем использовать шаблоны времени выполнения (предварительно обработанные) с пользовательскими свойствами, определенными в функциональном блоке класса <# + #> или в <# @ parameter #>Директива должна дать вам то, что вы хотите.

Посмотрите документы здесь: http://msdn.microsoft.com/en-us/library/gg586944.aspx

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

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

Другое решение заключается в использовании пользовательского шаблона, который использует подстановку шаблона в шаблоне t4, аналогично тому, как много установленошаблоны работают.

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

Эй - вам нужно установить значения и т.д. внутри скрипта T4, поэтому инициализация User должна происходить внутри тега <# #>, что превратит ваш пример во что-то похожее на

     <# User u1 = new User() { .Name = "John" } #>
     Hello <# u1.Name #> 

Как уже упоминалось выше, вам также может понадобиться импортировать пространства имен. Я использовал приведенные ниже утверждения в начале TT-файла, чтобы получить доступ к System.Data:

.
     <#@ import namespace="System.Data" #>
     <#@ import namespace="System.Data.SqlClient" #>
     <#@ assembly name="System.Data" #>
...