【问题标题】:How do I pass a string parameter to a t4 template如何将字符串参数传递给 t4 模板
【发布时间】:2013-04-11 10:47:25
【问题描述】:

您好,我正在尝试找到一种将普通字符串作为参数传递给文本模板的方法。

这是我的模板代码,如果有人能告诉我需要用 c# 编写什么来传递我的参数并创建类文件。这将非常有帮助,谢谢。

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

【问题讨论】:

    标签: c# string parameters t4 texttemplate


    【解决方案1】:

    以下是传递参数的一种方式:

    1. 您必须创建 TextTemplatingSession。
    2. 为参数设置会话字典。
    3. 使用该会话处理模板。

    示例代码(将 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);  #>
    

    我在 Oleg Sych 的博客上看到了这个 example,这是 t4 的绝佳资源。这是更新的链接:https://web.archive.org/web/20160706191316/http://www.olegsych.com/2010/05/t4-parameter-directive

    【讨论】:

    【解决方案2】:

    这是一个 3 年前的问题,我不知道模板库已经发展了多少,以及我的问题解决方案是否适用于旧版本的 Visual Studio 和/或 .NET 等。我目前正在使用Visual Studio 2015 和 .NET 4.6.1。

    总结

    使用“类功能控制块”向生成的模板类声明公共成员,并在模板文本中引用这些公共成员。

    示例

    在 C# 项目中,选择“添加新项”>“运行时文本模板”>“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 文章 Writing a T4 Text Template。

    【讨论】:

    • @Rice,它仍然对我有用。刚刚在 VS2017 的新控制台项目中尝试了我的示例的确切步骤。使用 .NET 4.7.1 的新建项目 > Visual C# > Windows 经典桌面 > 控制台应用程序 (.NET Framework)。仍然支持 T4。也许您正在尝试 .NET Core 项目。我认为 Core 不支持 T4。但在过去的几个月里,我个人已经切换到dotliquid,我对此非常满意。你应该试试看!它也适用于 Core。
    【解决方案3】:

    还可以在处理模板内容之前将参数注入模板内容。 为此,请将&lt;##&gt; 添加到您的模板中作为代码注入的占位符。

    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找到

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-02
      • 1970-01-01
      • 1970-01-01
      • 2021-02-24
      • 2011-06-29
      • 1970-01-01
      相关资源
      最近更新 更多