How do I pass a string parameter to a t4 template

The following is one way to pass parameters:

  1. You have to create TextTemplatingSession.
  2. Set the session dictionary for the parameters.
  3. Process the template using that session.

Sample code (Replace the ResolvePath with the location of your tt file):

<#@ 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);  #>

I saw this example on Oleg Sych's blog, which is great resource for t4.

This is a 3-year old question and I don't know how much the templating libraries have evolved and if my solution to the problem applies to older versions of Visual Studio and/or .NET etc. I'm currently using Visual Studio 2015 and .NET 4.6.1.

Summary

Use a "Class feature control block" to declare public members to the generated class of your template and refer to these public members in your template text.

Example

In a C# project select Add New Item > Runtime Text Template > "Salutation.tt". You get a new .tt file with the following default declarations:

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

Below the declarations enter your template text:

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

At the end of the .tt file add your parameters as public class members inside a "Class feature control block". This block must go to the end of the file.

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

Then, for example, in a Console Application, you can use your template as follows:

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

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

And get the following output:

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

For more information regarding the T4 syntax, see MSDN article Writing a T4 Text Template.

It is also possible to inject parameters to template content before processing it. To do it, add <##> to your template as a placeholder for code injection.

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

Than add a common template for importing other templates (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", "");
    }
#>

And then use it in any specific template, where you can just pass the necessary parameters (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);
#>

The complete example can be found at https://github.com/Konard/T4GenericsExample