Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pass an object to T4 template

I have an object u1 of type User class. User has an attribute name. How can I pass in u1 to a T4 template ? I am trying to do something very simple:

User u1 = new User("John"); 


Template script:

Hello <# u1.Name #>
like image 311
brainydexter Avatar asked May 31 '11 18:05

brainydexter


People also ask

What is .TT file in Entity Framework?

Text Template Transformation Toolkit, shortly written as T4, uses the . tt file extension for its source files. It is Microsoft's template-based text generation framework included with Visual Studio.


2 Answers

We did something similar to this. Our solution has the following elements:

  • Custom host
  • Custom template base class ("inherits" property of template directive)
  • Host specific templates ("hostspecific" property of template directive)

The custom host is aggregated by the object which the stencil itself wants to invoke methods on.

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;
        }
    }
}

Now, within any of our templates, we can invoke methods on the object who actually kicked off the processing using the custom host property, eg:

<# CustomHost.CallbackFxn(); #>

Also, we don't use T4 in VS or using a separate executable -- we link against the Microsoft.VisualStudio.TextTemplating.10.0 and Microsoft.VisualStudio.TextTemplating.Interfaces.10.0 assemblies.

EDIT

We're using T4 templates allow users to define their own plugins for use in a particular step in our product workflow. So user templates are uploaded to our system, and processed like this:

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
        }
    }
}
like image 119
gap Avatar answered Nov 11 '22 16:11

gap


Do you wanna use it in your template? Then you need to add a reference to the assembly containing the type. You cannot simply pass existing reference to the T4 engine unless you host it yourself in some highly unorthodox fashion (I've never seen anyone atempting to do this). And even if you went as far and did that how would you run it? Where is this reference supposed to come from?

Using the type from within a T4 template is as easy as adding the reference or copy/paste it in the class stub <#+ /*stuff goes here*/ #>.

like image 40
John Leidegren Avatar answered Nov 11 '22 15:11

John Leidegren